AOJ2284 The Legendary Sword
問題リンク The Legendary Sword
- 解法
DPです。数字kが書いてあるマス(i, j)に対して、そのマスに到達するまでの最短時間を記録しておきます。
宝珠が1つも無い場合もあるので注意してください。
- ソース
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner; //The Legendary Sword public class AOJ2284 { void run(){ Scanner sc = new Scanner(System.in); for(;;){ int w = sc.nextInt(); int h = sc.nextInt(); if((w|h)==0)break; int[][] map = new int[h][w]; List<int[]> l = new ArrayList<int[]>(); int[][] dist = new int[h][w]; int gi = -1, gj = -1; for(int[]a:map)Arrays.fill(a, 1<<29); int g = 1; for(int i=0;i<h;i++)for(int j=0;j<w;j++){ String s = sc.next(); char c = s.charAt(0); if(c=='S'){ l.add(new int[]{i, j}); dist[i][j] = 0; map[i][j] = 0; } else if(c=='G'){ map[i][j] = c; gi = i; gj = j; } else if(c=='.'){ map[i][j] = 0; } else{ map[i][j] = Integer.parseInt(s); g = Math.max(g, map[i][j]+1); } } map[gi][gj] = g; for(int x=1;x<=g;x++){ List<int[]> next = new ArrayList<int[]>(); for(int i=0;i<h;i++)for(int j=0;j<w;j++){ if(map[i][j]!=x)continue; next.add(new int[]{i, j}); int min = 1<<29; for(int[] a:l){ min = Math.min(min, dist[a[0]][a[1]]+Math.abs(a[0]-i)+Math.abs(a[1]-j)); } dist[i][j] = min; } l = next; } System.out.println(dist[gi][gj]); } } public static void main(String[] args) { new AOJ2284().run(); } }