牛客——小A与小B (双向广搜)
题意:
迷宫,小A每次可以移动一个位置,而小B每次可以移动两次位置,小A移动的方向是上下左右左上左下右上右下8个方向,小B移动的方向是上下左右4个方向,请问他们最早什么时候能够找到对方,如果他们最终无法相遇,那么就输出”NO"。
思路:
将A和B的起始位置都加到队列里,同时跑BFS,判断走过的位置是否已经被对方走过,如果走过的话,说明已经相遇了,输出即可。
要注意A和B走的方向和步数不一样。
代码:
#pragma GCC optimize(2) #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int>PII; #define I_int ll inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } char F[200]; inline void out(I_int x) { if (x == 0) return (void) (putchar('0')); I_int tmp = x > 0 ? x : -x; if (x < 0) putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0) putchar(F[--cnt]); cout<<endl; } const int maxn=1100; char mp[maxn][maxn]; struct node{ int x,y; }; queue<node>q[2]; int vis[2][maxn][maxn]; int n,m; int sx,sy,ex,ey; int nx[] = {1, -1, 0, 0, 1, -1, -1, 1}; int ny[] = {0, 0, 1, -1, -1, 1, -1, 1}; bool bfs(int u){ int tt=q[u].size(); while(tt--){ node t=q[u].front(); q[u].pop(); if(u==0){ for(int i=0;i<8;i++){ int xx=t.x+nx[i],yy=t.y+ny[i]; if(xx<1||yy<1||xx>n||yy>m||mp[xx][yy]=='#') continue; if(!vis[u][xx][yy]){ if(vis[u^1][xx][yy]) return true; vis[u][xx][yy] = 1; q[u].push({xx,yy}); } } } else{ for(int i=0;i<4;i++){ int xx=t.x+nx[i],yy=t.y+ny[i]; if(xx<1||yy<1||xx>n||yy>m||mp[xx][yy]=='#') continue; if(!vis[u][xx][yy]){ if(vis[u^1][xx][yy]) return true; vis[u][xx][yy] = 1; q[u].push({xx,yy}); } } } } return 0; } int sol(){ int res=0; vis[0][sx][sy]=1;vis[1][ex][ey]=1; q[0].push({sx,sy});q[1].push({ex,ey}); while(!q[0].empty()||!q[1].empty()){ res++; if(bfs(0)) return res; if(bfs(1)) return res; if(bfs(1)) return res; } return -1; } int main(){ scanf("%d %d", &n, &m); getchar(); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>mp[i][j]; if(mp[i][j]=='C'){ sx=i,sy=j; } else if(mp[i][j]=='D'){ ex=i,ey=j; } } } int tmp=sol(); if(tmp==-1) puts("NO"); else{ puts("YES"); cout<<tmp<<endl; } return 0; }