AOJ0542 Authentication Level
問題リンク Authentication Level
- 解法
a[i] (0 <= i <= W*H): i個の部屋を訪れるのに必要な最小認証レベル
という表を2つのマップについて作って解を調べる、というのが方針です。
マップの大きさが最大500*500と大きめなので少し工夫しないとTLEに引っかかると思います。
入り口を訪れたら、次の訪問先の候補は隣接している部屋です。その中で、必要な認証レベルが小さいものを訪問します。すると、さらに訪問する候補が増え、その中で最小認証レベルの部屋を訪れる、これを繰り返します。
候補の部屋を認証レベルの昇順になるようにPriorityQueueに突っ込みます。ただ、闇雲に突っ込むと同じ部屋を複数入れてしまって効率が悪いので、キューに入れたマークをつけていくといいと思います。
表ができたら、片方をr個、もう片方をR-r個訪れたときの認証レベルの和の最小値をとって解とします。
- ソース
import java.util.PriorityQueue; import java.util.Scanner; //Authentication Level public class AOJ0542 { class E implements Comparable<E>{ int k, i, j; public E(int k, int i, int j) { this.k = k; this.i = i; this.j = j; } public int compareTo(E o) { return k-o.k; } } int[][] d = {{-1,0},{0,1},{1,0},{0,-1}}; int[] f(int h, int w, int[][] a, int si, int sj){ int[] r = new int[w*h+1]; boolean[][] mark = new boolean[h][w], u = new boolean[h][w]; int id = 1, L = -1; mark[si][sj] = true; PriorityQueue<E> q = new PriorityQueue<E>(); q.add(new E(a[si][sj], si, sj)); while(!q.isEmpty()){ E e = q.poll(); if(L<e.k)L = e.k; u[e.i][e.j] = true; r[id++] = L; for(int k=0;k<4;k++){ int ni = e.i+d[k][0], nj = e.j+d[k][1]; if(0<=ni&&ni<h&&0<=nj&&nj<w&&!mark[ni][nj]){ mark[ni][nj] = true; q.add(new E(a[ni][nj], ni, nj)); } } } return r; } void run(){ Scanner sc = new Scanner(System.in); for(;;){ int R = sc.nextInt(); if(R==0)break; int[][] a = new int[2][]; for(int k=0;k<2;k++){ int w = sc.nextInt(), h = sc.nextInt(), sj = sc.nextInt()-1, si = sc.nextInt()-1; int[][] m = new int[h][w]; for(int i=0;i<h;i++)for(int j=0;j<w;j++)m[i][j]=sc.nextInt(); a[k] = f(h, w, m, si, sj); } int res = 1<<29; for(int r=0;r<=Math.min(R, a[0].length-1);r++){ if(a[1].length<=R-r)continue; res = Math.min(res, a[0][r]+a[1][R-r]); } System.out.println(res); } } public static void main(String[] args) { new AOJ0542().run(); } }