http://codeforces.com/contest/677/problem/D
建颗新树,节点元素包含r、c、dis,第i层包含拥有编号为i的钥匙的所有节点。用i-1层更新i层,逐层更新到底层。
不使用就会超时的优化:用i-1层更新时不是所有节点都有必要用到,我们对i-1层排序,取前600节点更新下层。
public class Main { private static final int c = 330,INF=Integer.MAX_VALUE/2,maxn=c*c*c+100,maxe=maxn*6; static class Node implements Comparable<Node>{ int x,y, dis; public Node(int x, int y, int dis) { this.x = x; this.y = y; this.dis = dis; } @Override public int compareTo(Node o) { return dis -o.dis; } } public static void main(String[] args) { IO io=new IO(); int n=io.nextInt(),m=io.nextInt(),p=io.nextInt(); ArrayList<Node>[]al=new ArrayList[p+1]; for (int i = 0; i < al.length; i++) al[i]=new ArrayList<>(c); int[]dis=new int[c*c]; Arrays.fill(dis,INF); for (int i=1;i<=n;i++)for (int j=1;j<=m;j++)al[io.nextInt()].add(new Node(i,j,INF)); al[0].add(new Node(1,1,0)); int ans=INF; for (int i=1;i<=p;i++){ Collections.sort(al[i-1]); for (int j=0;j<Math.min(al[i-1].size(),330);j++)for (Node k:al[i]){ k.dis=Math.min(k.dis,al[i-1].get(j).dis+Math.abs(k.x-al[i-1].get(j).x)+Math.abs(k.y-al[i-1].get(j).y)); if (i==p)ans=Math.min(k.dis,ans); } } io.println(ans); } }