ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 1525 퍼즐
    카테고리 없음 2020. 12. 6. 16:30

    www.acmicpc.net/problem/1525

     

    1525번: 퍼즐

    세 줄에 걸쳐서 표에 채워져 있는 아홉 개의 수가 주어진다. 한 줄에 세 개의 수가 주어지며, 빈 칸은 0으로 나타낸다.

    www.acmicpc.net

    2020-12-06


    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
     
    public class Main1525 {
        public static int answer;
        public static boolean flag;
        public static String base;
        public static HashSet<String> set;
        public static Queue<String> q;
        public static int dx[] = {-11-3 ,3};
        
        public static String swap(String sb, int cur, int next) {
            StringBuilder tmp = new StringBuilder(sb);
            char c = tmp.charAt(cur);
            char n = tmp.charAt(next);
            
            tmp.setCharAt(cur, n);
            tmp.setCharAt(next, c);
            
            return tmp.toString();
        }
        
        public static void solve() {
            loop:while(!q.isEmpty()) {
                int size = q.size(); 
                lop:while(size > 0) {
                    String str = q.poll();
                    int x = str.indexOf("0");
                    if(str.equals("123456780")) {
                        flag = true;
                        break lop;
                    }
                    for(int i = 0;i < dx.length; i++) {
                        int nx = x + dx[i];
                        
                        if(nx < 0 || nx >= 9 || (i == 1 && (x+1)%3 == 0 ) || (i == 0 && x % 3 == 0)) continue;
                        else {
                            String next = swap(str, x, nx);
                            if(!set.contains(next)) {
                                set.add(next);
                                q.add(next);
                            }
                        }
                    }
                    size--;
                }
                if(flag) break loop;
                answer++;
            }
        }
        
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            q = new LinkedList<>();
            flag = false;
            answer = 0;
            base = "";
            for(int i = 0 ; i <3; i++) {
                for(int j = 0; j < 3; j++) {
                    int x= sc.nextInt();
                    base += x;
                }
            }
            set = new HashSet<>();
            q.add(base);
            set.add(base);
            solve();
            if(flag) System.out.println(answer);
            else System.out.println("-1");
        }
    }
    cs

    브루트 포스(중복을 거르면서) + BFS로 풀었다.

     

    #문제 풀이

    1. 2차원 배열이 아닌 String 형태로 값을 받는다. 

     

    2. HashSet에 중복제거를 위하여, 새로운 퍼즐의 값들을 넣어준다. 그 첫번째로, 처음 입력 받은 값도 넣어준다.

     

    3. queue에 처음 입력받았던 string을 넣어주었다. 

     

    4. String형태에서 각 글자에 index를 생각하고, 0이 움직일 수 있는 인덱스를 생각하면 { -1, 1, -3, 3 } 4가지 방향이 나온다. queue에 값을 꺼내서 답이 "123456780" 이 아닌 경우는 이 4가지 방향대로 swap하면서, 새로운 String을 만든다. 이 때 HashSet을 사용하여, 중복이 아닌 경우에만 새로운 queue에 넣는다.

     

    # 포인트

    1. 메모리 초과

    - 메모리 제한이 있다. (32MB) 

    - 처음에는 class를 생성해서, current 0의 위치와 그 때의 String값을 동시에 저장했는데, 메모리 초과가 떴었다. 생각해보니 current 위치를 string과 함께 굳이 같이 들고 다닐 필요가 없었다.

     

    2. 이동 

    - 20%정도에서 계속 틀렸다고 떴었다. 0이 다음으로 이동할 index 값을 찾는데서 오류가 있었다.

     

    위 노란색 부분 ((index+1) % 3 == 0))에서 +1 (i == 1)로 이동하는 경우나, 초록색 부분 (index % 3 == 0) 에서 -1로 (i == 0)로 이동하는 경우는 배제되어야 한다. 0의 경우 next_index < 0 인 경우에서 걸러지게 된다.

    댓글

Programming Diary