题意:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210603193402404.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDE3ODczNg==,size_16,color_FFFFFF,t_70)
解法:
令d[i][j]表示到达点(i,j),且拿到该点a[i][j]钥匙的最小代价.
显然可以这样dp:
对于a[i][j]=x的所有点对(i,j),用a[u][v]=x-1的所有点对(u,v)进行更新.
但是暴力更新的复杂度是O((n*m)^2)的.
考虑优化:
令cnt[x]表示a[i][j]=x的格子数量,
1.当cnt[x-1]*cnt[x]<=n*m时,暴力O(cnt[x-1]*cnt[x])更新,总复杂度最多O(n*m*sq(n*m)).
2.当cnt[x-1]*cnt[x]>n*m时,进行多源bfs,从值为x-1的点向值为x的点bfs即可,
单次复杂度O(n*m),最多执行sq(n*m)次.
因此算法总复杂度为O(n*m*sq(n*m)),可以通过此题.
code:
#include<bits/stdc++.h>
#define int long long
#define PI pair<int,int>
using namespace std;
const int maxm=333;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
vector<PI>g[333*333];
int cnt[333*333];
int mp[333][333];
int d[333][333];
int a[333][333];
int n,m,p;
int cal(int x1,int y1,int x2,int y2){
return abs(x2-x1)+abs(y2-y1);
}
bool cmp(PI a,PI b){
return d[a.first][a.second]<d[b.first][b.second];
}
void update(PI x,PI y){
int cost=cal(x.first,x.second,y.first,y.second);
d[y.first][y.second]=min(d[y.first][y.second],d[x.first][x.second]+cost);
}
void bfs(int st,int ed){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
mp[i][j]=1e9;
}
}
queue<PI>q;
for(auto i:g[st]){
q.push(i);
mp[i.first][i.second]=d[i.first][i.second];
}
while(q.size()){
PI t=q.front();q.pop();
int x=t.first,y=t.second;
for(int i=0;i<4;i++){
int xx=x+dx[i];
int yy=y+dy[i];
if(xx<1||xx>n||yy<1||yy>m)continue;
if(mp[x][y]+1>=mp[xx][yy])continue;
mp[xx][yy]=mp[x][y]+1;
q.push({xx,yy});
}
}
for(auto i:g[ed]){
d[i.first][i.second]=mp[i.first][i.second];
}
}
void solve(){
cin>>n>>m>>p;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
d[i][j]=1e9;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
g[a[i][j]].push_back({i,j});
cnt[a[i][j]]++;
if(a[i][j]==1){
d[i][j]=cal(1,1,i,j);
}
}
}
for(int i=2;i<=p;i++){
if(cnt[i-1]*cnt[i]<=n*m){
for(auto x:g[i-1]){
for(auto y:g[i]){
update(x,y);
}
}
}else{
bfs(i-1,i);
}
}
int ans=1e9;
for(auto i:g[p]){
ans=min(ans,d[i.first][i.second]);
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
solve();
return 0;
}