AOJ0156 Moats around the Castle
問題リンク Moats around the Castle
- 解法
少し特殊な最短路問題と考えることができます。dist[i][j]を(i, j)までの最短距離として考えてたものを(i, j)にたどり着くまでに堀から上がる最小回数とすることができます。また、忍者はグリッドの周りのどこからでも侵入することができ、始点が沢山あって大変です。グリッドの周り全てを'.'で囲ってしまっても答えは変わらないので、'.'で囲んで適当な1か所から忍者を出発させればいいです。
(i, j)から(i', j')に忍者が動くとき、(i, j)が堀で(i', j')が堀じゃなければそこで堀を上がったことになります。(i', j')が天守閣の場合に上がった回数をカウントし損なうのに注意です。
- ソース
import java.util.Arrays; import java.util.Comparator; import java.util.PriorityQueue; import java.util.Scanner; //Moats around the Castle public class AOJ0156 { static int N, M; static boolean safe(int i, int j){ return 0<=i&&i<M&&0<=j&&j<N; } static int[][] d; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[][] move = {{0,1},{0,-1},{1,0},{-1,0}}; while(true){ int n = sc.nextInt(); int m = sc.nextInt(); if((n|m)==0)break; N = n+2; M = m+2; char[][] map = new char[M][N]; for(int i=0;i<M;i++)map[i][0]=map[i][N-1]='.'; for(int j=0;j<N;j++)map[0][j]=map[M-1][j]='.'; for(int i=1;i<=m;i++){ char[] s = sc.next().toCharArray(); for(int j=0;j<n;j++)map[i][j+1]=s[j]; } d = new int[M][N]; for(int i=0;i<M;i++)Arrays.fill(d[i], Integer.MAX_VALUE); d[0][0] = 0; PriorityQueue<int[]> q = new PriorityQueue<int[]>(M, new Comparator<int[]>() { public int compare(int[] o1, int[] o2) { return d[o1[0]][o1[1]]-d[o2[0]][o2[1]]; } }); q.add(new int[]{0,0}); int ans = Integer.MAX_VALUE; while(!q.isEmpty()){ int[] a = q.poll(); int i = a[0]; int j = a[1]; if(map[i][j]=='&'){ ans = Math.min(ans, d[i][j]); } for(int k=0;k<4;k++){ int ni = i+move[k][0]; int nj = j+move[k][1]; if(safe(ni,nj)){ int cost = d[i][j] + (map[i][j]=='#'&&map[ni][nj]!='#'?1:0); if(cost < d[ni][nj]){ d[ni][nj] = cost; q.add(new int[]{ni,nj}); } } } } System.out.println(ans); } } }