AtCoder Beginner Contest 176 D - Wizard in Maze ###K ###K ###K ###K //K
题目链接:https://atcoder.jp/contests/abc176/tasks/abc176_d
题意:给一个迷宫 #为不可走 每次可以移动到相邻的格子或者 用一次魔法 移动到以当前格子为中心的5×5的矩阵中的任何一个格子 问移动到终点要用魔法最少次数为多少
思路: 首先dfs 连最短路都求不出,除非回溯所有情况可以 不过肯定TLE 那么考虑bfs 但不能普通 以自己为中心的矩阵直接放入队列, 因为可能终点可以靠走相邻格子走到却不在5×5的格子中, 就会导致 次数不是最少次数
这其实是个经典的01bfs 问题 要用到双端队列, 相邻走的方式先放入队首, 用魔法的放入队尾
01bfs:
一般情况下,我们把没有权值的边扩展到的点放到队首,有权值的边扩展到的点放到队尾。
这样即可保证在整个队列中,像普通 BFS 一样,越靠近队首,权值越小,且权值零一之间有分隔。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define ull unsigned long long 7 #define pi pair<int,int> 8 #define fi first 9 #define sc second 10 #define pb push_back 11 12 int d[maxn][maxn]; 13 int st[maxn][maxn]; 14 char s[maxn][maxn]; 15 int n,m; 16 int s1,t1,s2,t2; 17 18 19 int xx[4]={0,0,1,-1}; 20 int yy[4]={1,-1,0,0}; 21 22 23 24 int main() 25 { 26 ios::sync_with_stdio(false); 27 cin.tie(0); 28 cin>>n>>m; 29 cin>>s1>>t1>>s2>>t2; 30 for(int i=1;i<=n;i++) 31 for(int j=1;j<=m;j++) 32 cin>>s[i][j]; 33 34 deque<pi>q; 35 q.push_back({s1,t1}); 36 memset(d,0x3f,sizeof(d)); 37 d[s1][t1]=0; 38 39 while(!q.empty()) 40 { 41 int x=q.front().fi,y=q.front().sc; 42 q.pop_front(); 43 44 45 if(st[x][y]) continue; 46 st[x][y]=1; 47 48 if(x==s2&&y==t2) 49 { 50 cout<<d[x][y]<<'\n'; 51 return 0; 52 } 53 54 for(int i=0;i<4;i++) 55 { 56 int tx=xx[i]+x; 57 int ty=yy[i]+y; 58 if(tx<1||tx>n||ty<1||ty>m||s[tx][ty]=='#') continue; 59 if(d[tx][ty]>=d[x][y]) 60 { 61 d[tx][ty]=d[x][y]; 62 q.push_front({tx,ty}); 63 } 64 } 65 for(int i=-2;i<=2;i++) 66 { 67 for(int j=-2;j<=2;j++) 68 { 69 int tx=x+i; 70 int ty=y+j; 71 if(tx<1||tx>n||ty<1||ty>m||s[tx][ty]=='#') continue; 72 if(d[tx][ty]>d[x][y]+1) 73 { 74 d[tx][ty]=d[x][y]+1; 75 q.push_back({tx,ty}); 76 } 77 } 78 } 79 } 80 cout<<-1<<'\n'; 81 82 83 84 85 }

浙公网安备 33010602011771号