import java.util.*;
class Solution {
static int oneJumpX[] = {1, -1, 0, 0};
static int oneJumpY[] = {0, 0, -1, 1};
static int twoJumpX[] = {2, -2, 0, 0};
static int twoJumpY[] = {0, 0, -2, 2};
public int solution(int n, int m, int[][] hole) {
int startX = m;
int startY = 1;
int endX = 1;
int endY = n;
int k = 1;
boolean visited[][][] = new boolean[m+1][n+1][k+1];
boolean MAP[][] = new boolean[m+1][n+1];
int holeLen = hole.length;
for(int i = 0; i < holeLen; i++) {
int x = startX - hole[i][1] + 1;
int y = hole[i][0];
MAP[x][y] = true;
}
Queue<Node> pq = new LinkedList<>();
pq.add(new Node(startX, startY, 0, k));
visited[startX][startY][k] = true;
int min = Integer.MAX_VALUE;
while(!pq.isEmpty()) {
Node nd = pq.poll();
if(nd.x == endX && nd.y == endY) {
if(min > nd.time) {
min = nd.time;
}
}
for(int i = 0; i < 4; i++) {
int n1x = nd.x + oneJumpX[i];
int n1y = nd.y + oneJumpY[i];
if(n1x > m || n1y > n || n1x < 1 || n1y < 1 || visited[n1x][n1y][nd.cnt] || MAP[n1x][n1y]) {
continue;
}
visited[n1x][n1y][nd.cnt] = true;
pq.offer(new Node(n1x, n1y, nd.time + 1, nd.cnt));
}
if(nd.cnt > 0) {
for(int i = 0; i < 4; i++) {
int n2x = nd.x + twoJumpX[i];
int n2y = nd.y + twoJumpY[i];
if(n2x > m || n2y > n || n2x < 1 || n2y < 1 || visited[n2x][n2y][nd.cnt - 1] || MAP[n2x][n2y]) {
continue;
}
visited[n2x][n2y][nd.cnt - 1] = true;
pq.offer(new Node(n2x, n2y, nd.time + 1, nd.cnt - 1));
}
}
}
return min == Integer.MAX_VALUE ? -1 : min;
}
static class Node {
int time;
int x;
int y;
int cnt;
public Node(int x, int y, int time, int cnt) {
this.x = x;
this.y = y;
this.time = time;
this.cnt = cnt;
}
}
}
진수는 보물이 묻힌 장소와 함정이 표시된 보물 지도를 이용해 보물을 찾으려 합니다. 보물지도는 가로 길이가 n, 세로 길이가 m인 직사각형 모양입니다.
맨 왼쪽 아래 칸의 좌표를 (1, 1)으로, 맨 오른쪽 위 칸의 좌표를 (n, m)으로 나타냈을 때, 보물은 (n, m) 좌표에 묻혀있습니다. 또한, 일부 칸에는 함정이 있으며, 해당 칸으로는 지나갈 수 없습니다.
진수는 처음에 (1, 1) 좌표에서 출발해 보물이 있는 칸으로 이동하려 합니다. 이동할 때는 [상,하,좌,우]로 인접한 네 칸 중 한 칸으로 걸어서 이동합니다. 한 칸을 걸어서 이동하는 데 걸리는 시간은 1입니다.
진수는 보물이 위치한 칸으로 수월하게 이동하기 위해 신비로운 신발을 하나 준비했습니다. 이 신발을 신고 뛰면 한 번에 두 칸을 이동할 수 있으며, 함정이 있는 칸도 넘을 수 있습니다. 하지만, 이 신발은 한 번밖에 사용할 수 없습니다. 신비로운 신발을 사용하여 뛰어서 두 칸을 이동하는 시간도 1입니다.
이때 진수가 출발점에서 보물이 위치한 칸으로 이동하는데 필요한 최소 시간을 구해야 합니다.
예를 들어, 진수의 보물지도가 아래 그림과 같을 때, 진수가 걸어서 오른쪽으로 3칸, 걸어서 위쪽으로 3칸 이동하면 6의 시간에 보물이 위치한 칸으로 이동할 수 있습니다. 만약, 오른쪽으로 걸어서 1칸, 위쪽으로 걸어서 1칸, 신비로운 신발을 사용하여 위로 뛰어 2칸, 오른쪽으로 걸어서 2칸 이동한다면 총 5의 시간에 보물이 위치한 칸으로 이동할 수 있으며, 이보다 빠른 시간 내에 보물이 있는 위치에 도착할 수 없습니다.
진수의 보물지도가 표현하는 지역의 가로 길이를 나타내는 정수 n, 세로 길이를 나타내는 정수 m, 함정의 위치를 나타내는 2차원 정수 배열 hole이 주어졌을 때, 진수가 보물이 있는 칸으로 이동하는데 필요한 최소 시간을 return 하는 solution 함수를 완성해주세요. 단, 보물이 있는 칸으로 이동할 수 없다면, -1을 return 해야 합니다.
visited[n1x][n1y][nd.cnt] = true;
원래는 visited[n1x][n1y][0]은 그냥 이동했을 때
visited[n1x][n1y][1]은 마법의 신발을 신었을 때로
방문 체크 하려 했으나
각 객체가 가진 속성 값으로 판단하는게 맞았다
visited[n1x][n1y][nd.cnt] 같이 객체의 속성이
방문 체크의 조건에 부합하면 이미 그 속성 위치에
같은 속성의 객체가 방문했다는 것이기 때문에 그렇게 하는 것이 올바른 방법이다.