CF173B Chamber of Secrets ###K //K

题目链接:https://www.luogu.com.cn/problem/CF173B

题意:从1 1 射进一道向右的光线 每次遇到 # 的时候可以选择向四个方向发散一次, 或者沿原来的方向继续,

问能否最后到达n m的时候且 方向向右射出  求出最少的 #的发散次数

思路:因为题目满足01 bfs 的条件 所以直接考虑01bfs 对光线是否发散来处理

要注意的是  当到达n m 方向不为右 但是该格子是 # 的时候要特判 

 且vis要记录方向 来避免重复走

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define pb push_back
 5 const int mod=1e4;
 6 const int maxn=1e3+10;
 7 char s[maxn][maxn];
 8 int vis[maxn][maxn][5];
 9 int xx[5]={58,0,0,1,-1};
10 int yy[5]={58,1,-1,0,0};
11 //r l d u
12 
13 
14 struct ac
15 {
16     int x,y,step;
17     int f;
18 };
19 
20 
21 int main()
22 {
23     ios::sync_with_stdio(0);
24     cin.tie(0);
25     int n,m;
26     cin>>n>>m;
27     for(int i=1;i<=n;i++)
28     {
29         for(int j=1;j<=m;j++)
30         {
31             cin>>s[i][j];
32         }
33     }
34     int ans=-1;
35     deque<ac>q;
36     q.push_back({1,1,0,1});
37     vis[1][1][1]=1;
38     while(!q.empty())
39     {
40         ac u=q.front();
41         q.pop_front();
42         int x=u.x,y=u.y;
43         //cout<<x<<" "<<y<<" "<<u.f<<'\n';
44         if(x==n&&u.f==1)
45         {
46             cout<<x<<" "<<y<<'\n';
47             ans=u.step;
48             break;
49         }
50         if(x==n&&y==m&&s[x][y]=='#')
51         {
52             ans=u.step+1;
53             break;
54         }
55         int tx=x+xx[u.f],ty=y+yy[u.f];
56         if(tx<1||ty<1||tx>n||ty>m||vis[tx][ty][u.f])
57         {
58 
59         }
60         else
61         {
62             vis[tx][ty][u.f]=1;
63             q.push_front({tx,ty,u.step,u.f});
64         }
65         if(s[x][y]=='#')
66         {
67             for(int i=1;i<=4;i++)
68             {
69                 int tx=xx[i]+x;
70                 int ty=yy[i]+y;
71                 if(tx<1||ty<1||tx>n||ty>m||vis[tx][ty][i])
72                     continue;
73                 vis[tx][ty][i]=1;
74                 q.push_back({tx,ty,u.step+1,i});
75             }
76         }
77     }
78     cout<<ans<<'\n';
79 
80 
81 }
82 /*
83 5 5
84 .##..
85 .##..
86 .#.#.
87 ..#..
88 ..#..
89 */
View Code

 或者直接考虑 起点为 n m+1 终点为1 0  直接写也行 特判边界

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e3+10;
 4 const int mod=998244353;
 5 #define ll long long
 6 #define pb push_back
 7 #define pi pair<int,int>
 8 #define fi first
 9 #define sc second
10 int n,m;
11 char s[maxn][maxn];
12 int xx[4]={-1,1,0,0};
13 int yy[4]={0,0,-1,1};
14 
15 struct ac
16 {
17     int x,y,step,d;
18 };
19 int vis[maxn][maxn][4][2];
20 int solve()
21 {
22     vis[n][m+1][2][0]=1;
23     deque<ac>q;
24     q.push_back({n,m+1,0,2});
25     while(!q.empty())
26     {
27         ac u=q.front();
28         q.pop_front();
29         int x=u.x,y=u.y,step=u.step,d=u.d;
30         if(x==1&&y==0) return step;
31         if(s[x][y]=='#')
32         {
33             for(int i=0;i<4;i++)
34             {
35                 int tx=x+xx[i],ty=y+yy[i];
36                 if(tx==1&&ty==0)
37                 {
38                     q.push_back({tx,ty,step+1,i});
39                     vis[tx][ty][i][1]=1;
40                 }
41                 if(tx<1||tx>n||ty<1||ty>m||vis[tx][ty][i][1])
42                     continue;
43                 q.push_back({tx,ty,step+1,i});
44                 vis[tx][ty][i][1]=1;
45             }
46         }
47         int tx=x+xx[d],ty=y+yy[d];
48         if(tx==1&&ty==0) return step;
49         if(tx<1||tx>n||ty<1||ty>m||vis[tx][ty][d][0])
50             continue;
51         vis[tx][ty][d][0]=vis[tx][ty][d][1]=1;
52         q.push_front({tx,ty,step,d});
53     }
54     return -1;
55 }
56 
57 
58 int main()
59 {
60     ios::sync_with_stdio(0);
61     cin.tie(0);
62     cin>>n>>m;
63     for(int i=1;i<=n;i++) cin>>(s[i]+1);
64     cout<<solve()<<'\n';
65 
66 
67 
68 
69 
70 
71 }
View Code

 

posted @ 2020-11-28 20:39  canwinfor  阅读(81)  评论(0)    收藏  举报