01BFS
- 走的时候有两种走法,维护双端队列,一种走法代价是0,进入队首,另一种走法代价是?,放入队尾
题意
- 给定地图,给定n次起点和终点,每次输出最短时间
- 特别的,一个点可以向八个方向走,且向其中一个方向走不耗时,其他方向耗时为1
思路
- 与maze那道题类似,都需要处理队列中时间最短的,但本题不会出现跨越多种不同步长的情况,所以可以不用优先队列,使用一个双端队列来维护即可,对于每一个点尝试移动的时候,不耗时的方向直接放到队首,其余方向放到队尾,仍然保证了队列中耗时差不会超过1秒
AC代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int mp[1020][1020];
int vis[1020][1020];
int dir[8][2]={-1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1,-1,-1};
int bfs(int sx,int sy,int ex,int ey){
if(sx==ex&&sy==ey)return 0;
deque<pair<int,int>>q;
q.push_back({sx*(m+1)+sy,0});
while(q.size()){
int x=q.front().first/(m+1);
int y=q.front().first%(m+1);
int stp=q.front().second;
q.pop_front();
if(vis[x][y])continue;
if(x==ex&&y==ey)return stp;
vis[x][y]=1;
for(int i=0;i<8;i++){
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if(tx<1||ty<1||tx>n||ty>m||vis[tx][ty]){continue;}
if(i==mp[x][y]) q.push_front({tx*(m+1)+ty,stp});
else q.push_back({tx*(m+1)+ty,stp+1});
}
}
return -1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%1d",&mp[i][j]);
}
}
int t;
scanf("%d",&t);
int sx,sy,ex,ey;
while(t--){
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
memset(vis,0, sizeof(vis));
printf("%d\n",bfs(sx,sy,ex,ey));
}
return 0;
}
PS
- 1起点的坐标转化为一个数的时候是x*(m+1)+y,调半天,烦死