AOJ2419 Acrophobia

問題リンク Acrophobia

  • 解法

全マスについて移動コストを求めた後、集める巻物の順序を全探索します。
巻物の本数が5本以下と小さいので、DPを使うまでもないと思います。

  • ソース
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;

//Acrophobia
public class AOJ2419 {

	int w, h, si, sj, gi, gj, S, G, M, INF = 1<<29, res;
	int[][] adj;
	int[][] dist;
	int[][] d = {{-1,0},{0,1},{1,0},{0,-1}};
	boolean[] v;
	void f(int id, int sum){
		if(id==G){
			res = Math.min(res, sum); return;
		}
		if(res<=sum)return;
		boolean f = true;
		for(int i=0;i<M;i++)if(i!=G && !v[i]){
			f = false;
			v[i] = true;
			f(i, sum+adj[id][i]);
			v[i] = false;
		}
		if(f)f(G, sum+adj[id][G]);
	}
	
	void run(){
		Scanner sc = new Scanner(System.in);
		w = sc.nextInt(); h = sc.nextInt();
		char[][] m = new char[h][w];
		M = 0;
		int[][] cost = new int[h][w];
		int[][] id = new int[h][w];
		for(int i=0;i<h;i++)for(int j=0;j<w;j++){
			cost[i][j]=1;
			id[i][j] = -1;
		}
		for(int i=0;i<h;i++){
			m[i] = sc.next().toCharArray();
			for(int j=0;j<w;j++){
				if(m[i][j]=='S'){
					m[i][j] = '.';
					si = i; sj = j;
					S = M;
					id[i][j] = M++;
				}
				if(m[i][j]=='G'){
					m[i][j] = '.';
					gi = i; gj = j;
					G = M;
					id[i][j] = M++;
				}
				if(m[i][j]=='M'){
					m[i][j] = '.';
					id[i][j] = M++;
				}
				if(m[i][j]=='#'){
					for(int y=i-2;y<=i+2;y++)for(int x=j-2;x<=j+2;x++){
						if(0<=y&&y<h&&0<=x&&x<w)cost[y][x] = Math.max(cost[y][x], 2);
					}
					for(int y=i-1;y<=i+1;y++)for(int x=j-1;x<=j+1;x++){
						if(0<=y&&y<h&&0<=x&&x<w)cost[y][x] = Math.max(cost[y][x], 3);
					}
				}
			}
		}
		adj = new int[M][M];
		for(int i=0;i<h;i++)for(int j=0;j<w;j++)if(id[i][j]!=-1){
			int now = id[i][j];
			dist = new int[h][w];
			for(int[]d:dist)Arrays.fill(d, INF);
			dist[i][j] = 0;
			PriorityQueue<int[]> q = new PriorityQueue<int[]>(h*w, new Comparator<int[]>() {
				public int compare(int[] o1, int[] o2) {
					return dist[o1[0]][o1[1]] - dist[o2[0]][o2[1]];
				}
			});
			q.add(new int[]{i, j});
			while(!q.isEmpty()){
				int[] V = q.poll();
				int pi = V[0], pj = V[1];
				for(int k=0;k<4;k++){
					int ni = pi+d[k][0], nj = pj+d[k][1];
					if(0<=ni&&ni<h&&0<=nj&&nj<w&&m[ni][nj]!='#'){
						int w = dist[pi][pj] + cost[pi][pj];
						if(w < dist[ni][nj]){
							dist[ni][nj] = w; q.add(new int[]{ni, nj});
						}
					}
				}
			}
			for(int y=0;y<h;y++)for(int x=0;x<w;x++)if(id[y][x]!=-1)adj[now][id[y][x]] = dist[y][x];
		}
		res = INF;
		v = new boolean[M];
		v[S] = true;
		f(S, 0);
		System.out.println(res);
	}
	
	public static void main(String[] args) {
		new AOJ2419().run();
	}
}