[BOJ] 1525. 퍼즐- (Java)

Problem

제출일 : 2020-03-22

문제 풀이 시간 : 1H 30M

난이도 : ★★★


link : https://www.acmicpc.net/problem/1525

3×3 표에 다음과 같이 수가 채워져 있다. 오른쪽 아래 가장 끝 칸은 비어 있는 칸이다.

1 2 3
4 5 6
7 8

어떤 수와 인접해 있는 네 개의 칸 중에 하나가 비어 있으면, 수를 그 칸으로 이동시킬 수가 있다. 물론 표 바깥으로 나가는 경우는 불가능하다. 우리의 목표는 초기 상태가 주어졌을 때, 최소의 이동으로 위와 같은 정리된 상태를 만드는 것이다. 다음의 예를 보자.

1 3
4 2 5
7 8 6
1 2 3
4 5
7 8 6
1 2 3
4 5
7 8 6
1 2 3
4 5 6
7 8

가장 윗 상태에서 세 번의 이동을 통해 정리된 상태를 만들 수 있다. 이와 같이 최소 이동 횟수를 구하는 프로그램을 작성하시오.

Input

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

Output

첫째 줄에 최소의 이동 횟수를 출력한다. 이동이 불가능한 경우 -1을 출력한다.

Example

input

1 0 3
4 2 5
7 8 6

output

3

Solution & Inpression

맵의 상태를 정수형으로 변환 Set자료구조를 이용한 방문 확인

Code

언어 : JAVA

메모리 : 63944 kb

실행 시간 : 688 ms

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Gold3_1525_퍼즐 {
    static int[] dr = { -1, 1, 0, 0 };
    static int[] dc = { 0, 0, -1, 1 };

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int map = 0;
        int[] start = new int[2];
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                int tmp = sc.nextInt();
                map *= 10;
                map += tmp;
                if (tmp == 0) {
                    map += 9;
                    start[0] = i;
                    start[1] = j;
                }
            }
        }
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[] { map, start[0], start[1], 0 });
        Set<Integer> set = new TreeSet<>();
        set.add(map);
        while (!q.isEmpty()) {
            if (q.peek()[0] == 123456789) {
                System.out.println(q.peek()[3]);
                System.exit(0);
            }

            char[] now = ("" + q.peek()[0]).toCharArray();
            int r = q.peek()[1];
            int c = q.peek()[2];
            int cnt = q.peek()[3];
            q.poll();

            for (int k = 0; k < dr.length; k++) {
                int nr = r + dr[k];
                int nc = c + dc[k];
                if (isRange(nr, nc)) {
                    int next = getNext(now, r * 3 + c, nr * 3 + nc);
                    if (!set.contains(next)) {
                        set.add(next);
                        q.offer(new int[] { next, nr, nc, cnt + 1 });
                    }
                }
            }
        }
        System.out.println(-1);
    }

    private static int getNext(char[] now, int i, int j) {
        char tmp = now[i];
        now[i] = now[j];
        now[j] = tmp;
        int ret = 0;
        for (char c : now) {
            ret *= 10;
            ret += c - '0';
        }
        tmp = now[i];
        now[i] = now[j];
        now[j] = tmp;
        return ret;
    }

    private static boolean isRange(int nr, int nc) {
        if (0 <= nr && nr < 3 && 0 <= nc && nc < 3)
            return true;
        return false;
    }

}

'Problem > BOJ' 카테고리의 다른 글

[BOJ] 12851. 숨바꼭질2 - (Java)  (0) 2020.03.22
[BOJ] 2251. 물통 - (Java)  (0) 2020.03.22
[BOJ] 1175. 배달 - (Java)  (0) 2020.03.22
[BOJ] 1039. 교환 - (Java)  (0) 2020.03.21
[BOJ] 1072. 게임 - (Java)  (0) 2020.03.18