Super Jaber(dfs预处理)
题目大意:给出一个n*m的矩阵,每个点都有一个颜色,颜色的种类不超过40种,如果想从一个点到达另一个点,有两种方法:
- 花费一个单位的时间从某种颜色闪现到相同的颜色
- 花费一个单位的时间走到相邻的格子中
现在给出 q 个询问,每次询问回答从起点到终点的最短时间
,首先我们需要预处理出 dis[ color ][ x ][ y ] 数组,代表的是从点 ( x , y ) 到 color 颜色的最短路,这样对于每个询问,我们就可以枚举每个颜色为中转点维护最小值了,最后和他们的
曼哈顿距离取个最大值
#include<iostream> #include<algorithm> #include<queue> #include<cstring> using namespace std; const int maxn=1e3+100; int a[maxn][maxn]; int d[43][maxn][maxn]; int vis[maxn]; struct node{ int x,y; }; vector<node>c[maxn]; int dx[]={0,0,-1,1}; int dy[]={1,-1,0,0}; int n,m,k; //f[k][i][j]表示从格子(i,j)到一个颜色为k的格子的最少步数 void bfs(int k){ queue<node>q; memset(vis,0,sizeof(vis)); for(int i=0;i<c[k].size();i++){ node p=c[k][i]; int x=p.x,y=p.y; d[k][x][y]=0; q.push({x,y}); } vis[k]=1; while(!q.empty()){ node top=q.front(); q.pop(); int tx=top.x,ty=top.y,td=d[k][top.x][top.y],tc=a[top.x][top.y]; if(!vis[tc]){ vis[tc]=1; for(int i=0;i<c[tc].size();i++){ int x=c[tc][i].x,y=c[tc][i].y; if(d[k][x][y]!=-1){ continue; } d[k][x][y]=td+1; q.push({x,y}); } } for(int i=0;i<4;i++){ int x=tx+dx[i]; int y=ty+dy[i]; if(x>=1&&x<=n&&y>=1&&y<=m&&d[k][x][y]==-1){ d[k][x][y]=td+1; q.push({x,y}); } } } } int main(){ cin>>n>>m>>k; memset(d,-1,sizeof(d)); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>a[i][j]; c[a[i][j]].push_back({i,j}); } } for(int i=1;i<=k;i++){ bfs(i); } int q; cin>>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); for(int i=1;i<=k;i++){ ans=min(ans,d[i][x1][y1]+d[i][x2][y2]+1); } cout<<ans<<"\n"; } }