본문 바로가기

Algorithm

백준 1525 퍼즐 Java

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.Scanner;
 
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 = {001-1};
        int[] dy = {1-100};
        
        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