동굴의 각 칸에는 도둑루피가 있다.
시작점 (0,0) 도착점(n-1,n-1)
문제의 N의 크기는 125 이하다.
.... PQ 에 넣던 시점의 cost 가 아닌, 동적으로 계속 변하고 있는 cost 테이블의 값을 사용해, PQ에서 compare을 하도록 하고 있었다.
public class Main {
public static int n;
public static int[][] board; // 보드의 각 칸은 -> 각칸의 도둑루피
public static int[][] cost; // 각 칸까지의 최소 비용
public static PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[2] - o2[2];
}
});
public static int[][] dirs = new int[][] {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// public static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static StringTokenizer st;
public static void setUp() throws IOException {
int count = 1;
while (true) {
String temp = br.readLine();
if (temp.equals("0"))
return;
n = Integer.parseInt(temp);
board = new int[n][n];
cost = new int[n][n];
// init board
for (int r = 0; r < n; r++) {
st = new StringTokenizer(br.readLine());
for (int c = 0; c < n; c++) {
board[r][c] = Integer.parseInt(st.nextToken());
}
}
// init cost
IntStream.range(0, n)
.forEach(i -> Arrays.fill(cost[i], Integer.MAX_VALUE));
cost[0][0] = board[0][0];
System.out.println("Problem "+count++ +": "+solve());
}
}
public static int solve() {
pq.clear();
pq.add(new int[] {0, 0, cost[0][0]});
while (!pq.isEmpty()) {
// 현재 까지에서 최소 거리인 노드를 추출한다
int[] cur = pq.poll();
int curCost = cost(cur[0], cur[1]);
// 도착점에 도달하면 바로 리턴
if (cur[0] == n - 1 && cur[1] == n - 1)
return curCost;
// 인접 노드
for (int d = 0; d < dirs.length; d++) {
int nr = cur[0] + dirs[d][0];
int nc = cur[1] + dirs[d][1];
if (nr < 0 || nc < 0 || nr >= n || nc >= n)
continue;
int nCost = curCost + board[nr][nc];
if (cost[nr][nc] > nCost) {
pq.add(new int[] {nr, nc, nCost});
cost[nr][nc] = nCost;
}
}
}
return cost(n - 1, n - 1);
}
public static int cost(int r, int c) {
return cost[r][c];
}
public static void main(String[] args) throws IOException {
setUp();
}
}