题解:
这东西就是分层DP
考虑dp ( i , j )表示到位置( i , j )的最短长度
然后可以枚举上一次的位置转移过来
这样单次转移复杂度和两层中点的数量有关
这样复杂度显然是O((nm)^2)的,爆炸
考虑另一种暴力,每次转移时bfs,这样单次转移复杂度O(nm)
考虑根号分治,当两层点数乘积>nm时用bfs,这种情况不会超过sqrt(nm)个
然后两层点数乘积<nm时,考虑暴力DP转移
复杂度O(nmsqrt(nm))

1 #include<bits/stdc++.h> 2 #define maxn 305 3 #define pii pair<int,int> 4 #define mp(a,b) make_pair(a,b) 5 using namespace std; 6 int n,m,p; 7 vector<pii> v[maxn*maxn]; 8 struct node 9 { 10 pii pos; 11 int dis; 12 node(){} 13 node(pii P,int D){pos=P;dis=D;} 14 }; 15 bool operator < (node a,node b) 16 { 17 return a.dis<b.dis; 18 } 19 int ans[maxn][maxn],dis[maxn][maxn]; 20 bool vis[maxn][maxn]; 21 int Ax,Ay; 22 int main() 23 { 24 scanf("%d%d%d",&n,&m,&p); 25 for(int i=1;i<=n;++i) 26 for(int j=1;j<=m;++j) 27 { 28 int x; 29 scanf("%d",&x); 30 v[x].push_back(mp(i,j)); 31 if(x==p)Ax=i,Ay=j; 32 } 33 memset(ans,127/2,sizeof(ans)); 34 for(int i=0;i<v[1].size();++i) 35 { 36 int x=v[1][i].first,y=v[1][i].second; 37 ans[x][y]=abs(x-1)+abs(y-1); 38 } 39 for(int i=2;i<=p;++i) 40 { 41 if(v[i-1].size()*v[i].size()<n*m) 42 { 43 for(int j=0;j<v[i].size();++j) 44 { 45 for(int k=0;k<v[i-1].size();++k) 46 { 47 int x=v[i][j].first,y=v[i][j].second; 48 int u=v[i-1][k].first,w=v[i-1][k].second; 49 ans[x][y]=min(ans[x][y],ans[u][w]+abs(x-u)+abs(y-w)); 50 } 51 } 52 } 53 else 54 { 55 const int dx[]={-1,0,1,0}; 56 const int dy[]={0,-1,0,1}; 57 memset(dis,0,sizeof(dis)); 58 memset(vis,0,sizeof(vis)); 59 vector<node> t; 60 queue<node> q1,q2; 61 for(int j=0;j<v[i-1].size();++j)t.push_back(node(v[i-1][j],ans[v[i-1][j].first][v[i-1][j].second])); 62 sort(t.begin(),t.end()); 63 for(int j=0;j<t.size();++j) 64 { 65 q2.push(t[j]); 66 int x=t[j].pos.first,y=t[j].pos.second; 67 vis[x][y]=1; 68 dis[x][y]=t[j].dis; 69 } 70 while(!q1.empty()||!q2.empty()) 71 { 72 node u; 73 if(q1.empty())u=q2.front(),q2.pop(); 74 else if(q2.empty())u=q1.front(),q1.pop(); 75 else 76 { 77 if(q1.front().dis<q2.front().dis)u=q1.front(),q1.pop(); 78 else u=q2.front(),q2.pop(); 79 } 80 int x=u.pos.first,y=u.pos.second; 81 for(int k=0;k<4;++k) 82 { 83 int nx=x+dx[k],ny=y+dy[k],nd=u.dis+1; 84 if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&(!vis[nx][ny])) 85 { 86 vis[nx][ny]=1; 87 dis[nx][ny]=nd; 88 q1.push(node(mp(nx,ny),nd)); 89 } 90 } 91 } 92 for(int j=0;j<v[i].size();++j) 93 { 94 int x=v[i][j].first,y=v[i][j].second; 95 ans[x][y]=dis[x][y]; 96 } 97 } 98 } 99 printf("%d ",ans[Ax][Ay]); 100 return 0; 101 }