题意:
现在有一张n*m的矩形图,每个格子有一个颜色,并且每个格子都可以花一秒的时间往周围四格扩散或者跳到另一个相同颜色的位置。每次问你从(x1,y1)跳到(x2,y2)至少要花多少时间
题解:
首先如果直接走是最短的那么就直接走,否则就一定至少会在一个颜色进行跳转。
dis[c][i][j]表示从颜色c跳到位置(i,j)的最少时间
那么直接进行bfs,首先如果这个颜色没跳过,就进行跳转,否则就往旁边进行扩散即可。
#include<bits/stdc++.h>
using namespace std;
#define pa pair<int,int>
const int N=1e3+5,M=45;
int dis[M][N][N],mp[N][N],n,m,q,k;
queue<pa>Q;
int xmov[]={1,0,-1,0};
int ymov[]={0,1,0,-1};
int cal[M];
void bfs(int c){
memset(cal,0,sizeof(cal));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]==c)
Q.push({i,j});
while(!Q.empty()){
int x=Q.front().first,y=Q.front().second;Q.pop();
if(!cal[mp[x][y]]&&mp[x][y]!=c){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==x&&j==y)continue;
if(mp[i][j]==mp[x][y]&&!dis[c][i][j])
dis[c][i][j]=dis[c][x][y]+1,Q.push({i,j});
}
}
cal[mp[x][y]]=1;
}
for(int i=0;i<4;i++){
int nx=x+xmov[i],ny=y+ymov[i];
if(nx<1||nx>n||ny<1||ny>m||dis[c][nx][ny]||mp[nx][ny]==c)continue;
dis[c][nx][ny]=dis[c][x][y]+1;
Q.push({nx,ny});
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&mp[i][j]);
for(int i=1;i<=k;i++)
bfs(i);
scanf("%d",&q);
while(q--){
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int ans=abs(x1-x2)+abs(y1-y2);
//if(mp[x1][y1]==mp[x2][y2])ans=1;
if(x1==x2&&y1==y2)ans=0;
for(int i=1;i<=k;i++)
ans=min(ans,dis[i][x1][y1]+dis[i][x2][y2]+1);
printf("%d\n",ans);
}
return 0;
}