BFS를 이용한 완전 탐색을 통해 풀 수 있는 퍼즐 문제이다.
이 문제는 다른 BFS문제와는 다르게 0의 위치만 예제와 맞게 구현하면 안 되고
1부터 8까지의 수의 위치도 맞아야 하기 때문에 까다롭다.
먼저 편하게 풀기 위해 입력받은 값에서
초기 값인
1 2 3
4 5 6
7 8 0
으로 이동하는 문제로 바꿔서 풀고
2차원 배열은 까다롭기 때문에 1차원 배열로 바꾸어서 풀고
Map인터페이스를 이용해서 이동한 횟수를 저장하면서 풀어야 한다.
첫 번째 예제의 값
1 0 3
4 2 5
7 8 6
을 예로 보면
1 0 3 4 2 5 7 8 6으로 바꾼다.
그리고 0 대신에 9를 넣어준다.
1 9 3 4 2 5 7 8 6
이 1차원 배열을
1 2 3 4 5 6 7 8 9로 바꾸는 데 걸린 최소 횟수를 출력하면 되는 문제가 된다.
9가 상하좌우로 이동 할 수 있기 때문에
큐를 사용한 BFS로 상하좌우 전부 이동시키면서
모든 경우의 수를 해보면 된다.
입력받은 수들을 1차원 배열로 저장하고 0을 9로 바꾸기 위한 코드는 이렇다.
1
2
3
4
5
6
7
8
9
10
11
|
int start = 0;
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
int k = scan.nextInt();
if(k == 0) { //0을 9로 바꿈
k = 9;
}
start = (start*10) +k; //2차원배열을 하나의 정수로 나타내기 위해서
}
}
|
입력받은 값을 하나의 정수로 나타낸 후 String으로 변환해 9의 인덱스를 찾고
9의 인덱스에서 이동할 상하좌우의 인덱스를 찾아야 한다.
이때 상하좌우는 2차원 배열에서의 기준이기 때문에
9의 인덱스를 2차원 배열 버전으로 구해야 한다.
행을 구하기 위해서는 9의 인덱스 / 3을
열을 구하기 위해서는 9의 인덱스 % 3을 하면 된다.
이렇게 구한 2차원 배열 버전에서의 행, 열을 통해 상하좌우의 인덱스를 알아내고
그 인덱스를 다시 (행*3 + 열)을 해주면 1차원 배열에서의 이동할 상하좌우의 인덱스를 알아낼 수 있다.
그리고 원래의 숫자에서 상하좌우로 이동할 인덱스와 9를 스왑 해주고 큐에 넣어주고 Map에도 이동횟수를 넣어준다.
설명이 굉장히 너저분하지만 코드를 읽어보면 충분히 이해할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
public class Q1525 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int start = 0;
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
int k = scan.nextInt();
if(k == 0) { //0을 9로 바꿈
k = 9;
}
start = (start*10) +k; //2차원배열을 하나의 정수로 나타내기 위해서
}
}
Queue<Integer> q = new LinkedList<>();
Map<Integer, Integer> m = new HashMap<>();
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
m.put(start, 0);
q.add(start);
while(!q.isEmpty()) {
int nowNum = q.poll();
String now = String.valueOf(nowNum);
int nine = now.indexOf("9"); //9의 인덱스를 찾는다.
int x = nine / 3; // 9가 2차원배열에서 몇 번째 행인지 계산
int y = nine % 3; // 9가 2차원배열에서 몇 번째 열인지 계산
for(int i=0; i<4; i++) {
int nx = x+dx[i]; //이동할 상하좌우의 행 계산
int ny = y+dy[i]; //이동할 상하좌우의 열 계산
int move = nx*3+ny; //이동할 상하좌우의 1차원배열에서의 인덱스
if (nx >= 0 && nx < 3 && ny >= 0 && ny < 3) {
StringBuilder next = new StringBuilder(now);
//9와 이동할 상하좌우 스왑하기
char temp = next.charAt(move);
next.setCharAt(move, '9'); //이동할 인덱스에 9를
next.setCharAt(nine, temp); //원래 9자리에 이동한 곳의 수를
int nextNum = Integer.parseInt(next.toString());
if(!m.containsKey(nextNum)) { //맵에 몇 번이동했는지 저장
m.put(nextNum, m.get(nowNum)+1);
q.add(nextNum);
}
}
}
}
if(m.containsKey(123456789)) {
System.out.println(m.get(123456789));
}
else
System.out.println(-1);
}
}
|
'Algorithm' 카테고리의 다른 글
백준 1946 신입 사원 Java (4) | 2019.06.10 |
---|---|
백준 1120 문자열 Java (0) | 2019.06.10 |
백준 9019 DSLR Java (0) | 2019.06.08 |
백준 1963 소수 경로 Java (0) | 2019.06.08 |
완전 탐색(exhaustive - search)의 종류 (0) | 2019.06.07 |