[BOJ12886] 돌 그룹
문제 설명
- A, B, C 숫자 세개가 입력으로 주어진다.
- 세 개의 숫자 중, 크기가 다른 두 개를 선택한다.(작은 수를 X, 큰 수를 Y)
- X는 X+X로, Y는 Y-X로 만든다.
- 이렇게 반복했을 때, 세개의 돌을 모두 같은 수로 만들 수 있는지 없는지를 판단하는 문제이다.
생각의 흐름
- 완전탐색으로 풀 수 있다는 생각을 처음에 하지 못하고, 수학적인 방법이 있을거라고 생각하고 접근했다.
- 하지만 풀이를 생각하다 보니, A,B,C는 변형이 일어나도 늘 합이 같고, 가지 수가 생각보다 늘어나지 않는다는 것을 알게 되었다.
- A, B, C에서 2개를 골라 A’, B’로 변형을 시키고, C는 sum - (A’ + B’)로 구할 수 있었다.
- 이렇게 세개의 숫자를 visit에 저장해서(실제 저장할 땐 3개를 다 저장하진 않는다.) 방문 체크를 해주었고, 모든 경우의 탐색이 끝났을 때 세 숫자의 합이 동일한 경우가 없었다면 false를 리턴해준다.
풀이
- bfs를 도는 큐에 a,b,c를 담고있는 노드를 저장하고, 처음 세개의 숫자의 합을 저장해둔다.
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
sum = a + b + c;
q.add(new Node(a, b, c));
- 큐에서 뺀 노드를 통해, 순차적으로 다음에 나타날 수 있는 숫자들을 파악한다.
- a,b,c 세개의 숫자 중에 선택할 수 있는 2개의 숫자의 조합은 (a,b) , (b,c), (c,a) 이다.
- 이를 통해 다음 숫자를 만들어낸다.
- 다음 숫자를 만들기 전, 현재 숫자가 모두 같은 숫자이면 true를 반환한다.
Node now = q.poll();
int[][] d = { {now.a, now.b, now.c}, {now.b, now.c, now.a} };
if (now.a == now.b && now.b == now.c) {
return 1;
}
for (int k = 0; k < 3; k++) {
int na = d[0][k];
int nb = d[1][k];
if (na < nb) {
nb -= na;
na += na;
} else if (na > nb) {
na -= nb;
nb += nb;
}
int nc = sum - (na + nb);
}
- 두 개만 구하면 자동적으로 다음 레벨의 다른 하나의 숫자는 sum을 통해 구할 수 있다.
- visit 배열은 2개의 숫자로만 판단하는데, 세개의 숫자중 가장 큰 숫자와 가장 작은 숫자가 있으면, 중간 숫자 역시 sum을 통해 정해져있기 때문에 visit 배열은 2차원 배열로 생성하였다.
int max = Math.max(Math.max(na, nb), nc);
int min = Math.min(Math.min(na, nb), nc);
if (!visit[max][min]) {
visit[max][min] = true;
q.add(new Node(na, nb, nc));
}
- 생각보다 풀고나니 간단했던 문제였다.
- 전체 코드를 첨부한다.
import java.io.*;
import java.util.*;
public class Main {
private static int sum = 0;
private static boolean[][] visit = new boolean[1500][1500];
private static Queue<Node> q = new LinkedList<>();
public static void main(String[] args) throws IOException {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(input.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
sum = a + b + c;
q.add(new Node(a, b, c));
System.out.println(bfs());
}
private static int bfs() {
while (!q.isEmpty()) {
Node now = q.poll();
int[][] d = { {now.a, now.b, now.c}, {now.b, now.c, now.a} };
if (now.a == now.b && now.b == now.c) {
return 1;
}
for (int k = 0; k < 3; k++) {
int na = d[0][k];
int nb = d[1][k];
if (na < nb) {
nb -= na;
na += na;
} else if (na > nb) {
na -= nb;
nb += nb;
}
int nc = sum - (na + nb);
int max = Math.max(Math.max(na, nb), nc);
int min = Math.min(Math.min(na, nb), nc);
if (!visit[max][min]) {
visit[max][min] = true;
q.add(new Node(na, nb, nc));
}
}
}
return 0;
}
private static class Node {
int a, b, c;
Node(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
}
댓글남기기