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 }
View Code

 

posted @ 2020-08-23 18:17  canwinfor  阅读(342)  评论(0)    收藏  举报