알고리즘/BOJ

[BOJ] 1600. 말이 되고픈 원숭이

재담 2022. 2. 27. 02:14

문제 원본 : https://www.acmicpc.net/problem/1600

 

1600번: 말이 되고픈 원숭이

첫째 줄에 정수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있

www.acmicpc.net

import java.io.*;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int k = Integer.parseInt(br.readLine());

        StringTokenizer st = new StringTokenizer(br.readLine());
        int w = Integer.parseInt(st.nextToken());
        int h = Integer.parseInt(st.nextToken());

        String[][] map = new String[h][w];
        for (int i = 0; i < h; ++i) {
            map[i] = br.readLine().split(" ");
        }

        boolean[][][] v = new boolean[h][w][k + 1];
        int[][][] dist = new int[h][w][k + 1];
        int[][] dir = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}, {-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
        Queue<Pos> q = new LinkedList<>();
        q.add(new Pos(0, 0, 0));

        v[0][0][0] = true;
        while (!q.isEmpty()) {
            Pos p = q.poll();
            for (int i = 0; i < 12; ++i) {
                int ny = p.y + dir[i][0];
                int nx = p.x + dir[i][1];

                if (ny >= 0 && nx >= 0 && ny < h && nx < w && map[ny][nx].equals("0")) {
                    if (i < 4 && !v[ny][nx][p.knight]) {
                        q.add(new Pos(ny, nx, p.knight));
                        dist[ny][nx][p.knight] = dist[p.y][p.x][p.knight] + 1;
                        v[ny][nx][p.knight] = true;
                    } else if (i >= 4 && p.knight < k && !v[ny][nx][p.knight + 1]) {
                        q.add(new Pos(ny, nx, p.knight + 1));
                        dist[ny][nx][p.knight + 1] = dist[p.y][p.x][p.knight] + 1;
                        v[ny][nx][p.knight + 1] = true;
                    }
                }
            }
        }

        int ans = Integer.MAX_VALUE;
        boolean isPossible = false;
        for (int i = 0; i <= k; ++i) {
            if (v[h - 1][w - 1][i]) {
                isPossible = true;
                ans = Math.min(ans, dist[h - 1][w - 1][i]);
            }
        }

        bw.write(isPossible ? Integer.toString(ans) : Integer.toString(-1));

        bw.close();
        br.close();
    }

    public static class Pos {
        public int y;
        public int x;
        public int knight;

        public Pos(int y, int x, int knight) {
            this.y = y;
            this.x = x;
            this.knight = knight;
        }
    }
}
  • 2206. 벽 부수고 이동하기 문제와 유사한 문제이다.
  • 다른 점은 벽 부수는 건 한 번까지만 되고 말처럼 이동하는 건 k번만큼 가능하다는 것뿐이다.
  • 이제 이런 BFS 유형은 감을 잡은 것 같다.

'알고리즘 > BOJ' 카테고리의 다른 글

[BOJ] 3190. 뱀  (0) 2022.03.01
[BOJ] 1074. Z  (0) 2022.02.28
[BOJ] 2206. 벽 부수고 이동하기  (0) 2022.02.27
[BOJ] 1406. 에디터  (0) 2022.02.26
[BOJ] 5639. 이진 검색 트리  (0) 2022.02.25