BFS
这道题要求小A和小B最早的相遇时间。
而小A的行走规则是:每次可以走8个方向,每次走一步
小B的行走规则是:每次可以走4个方向,但每次走两步(两步不一定是要同方向)
于是我们可以在每秒分别在对小A,小B每秒的行走进行讨论:
分别建立小A,小B的队列,依次对他俩进行
,并分别记录下行走中可以到达的点,若其中一人目前走到的点是另一人曾经走过的,则说明他们俩必定相遇,根据
的性质,当前时间一定是最优解。
注意:
- 在传统
里,while的结束条件是队列为空(q.size()或者!q.empty()),但在此题中,是对每秒的情况进行讨论,所以结束条件是当前
之前的队列元素全部讨论过一次,即设循环只需执行这次
前的q.size()次即可。
- 在对每秒的情况进行讨论时,若小A,小B已相遇,则可以跳出循环输出
,若未相遇,则讨论到小A,小B都走不动为止,有一个人还能走,就继续。
#include<bits/stdc++.h>//0->A 1->B
using namespace std;
const int dx[]={1,0,-1,0,1,1,-1,-1};
const int dy[]={0,1,0,-1,1,-1,1,-1};
int n,m;
char a[1005][1005];
bool vis[2][1005][1005];
struct node{
int x,y;
};
queue<node> q[2];
bool check_bfs(int w){
int Size=q[w].size();
while(Size--){
int x=q[w].front().x;
int y=q[w].front().y;
q[w].pop();
for(int k=0;k<(w?4:8);k++){
int tx=x+dx[k];
int ty=y+dy[k];
if(tx<1 || tx>n || ty<1 || ty>m || a[tx][ty]=='#' || vis[w][tx][ty]) continue;
if(vis[w^1][tx][ty]) return true;
q[w].push((node){tx,ty});
vis[w][tx][ty]=1;
}
}
return false;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(a[i][j]=='C'){
q[0].push((node){i,j});
vis[0][i][j]=1;
}
if(a[i][j]=='D'){
q[1].push((node){i,j});
vis[1][i][j]=1;
}
}
}
int tim=0;
bool flag=false;
while(q[0].size() || q[1].size()){
flag=false;
tim++;
if(q[0].size() && check_bfs(0)){
flag=true;
break;
}
if(q[1].size() && check_bfs(1)){
flag=true;
break;
}
if(q[1].size() && check_bfs(1)){
flag=true;
break;
}
}
if(flag){
puts("YES");
cout<<tim<<'\n';
}
else{
puts("NO");
}
return 0;
} 
京公网安备 11010502036488号