题意:
给出一张地图和小A和小B的位置,问两个人是否能在某一个点相遇,如果能相遇,那么需要的最短时间是多少。
思路:
首先肯定是要搜索了,首先分析小A,小A的行走方式简单,所以可以对小A BFS一遍,用一个数组记录小A到达这个位置所需要的最短时间,那么如果小B也能走到这个位置时,取所有可以走到公共地方时间的min即可。因此我们只需要在对小B BFS一遍,找出最小的时间就行,由于小B行走的方式比较麻烦,所以需要额外处理一下,如果最后答案不是初始值inf,说明可以相遇,否则不能,具体的见代码。
代码如下:
#include<bits/stdc++.h>
#define LL long long
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define db printf("Here!\n");
using namespace std;
const LL inf=2e9;
const int N=1e3+5;
const int mod=1e9+7;
int n,m,k,t,T,ans=inf,bx,by,ex,ey;
int step[N][N],dir[8][2]={{-1,-1},{-1,1},{1,-1},{1,1},{1,0},{-1,0},{0,1},{0,-1}};//方向数组
char maze[N][N];
bool vis[N][N];
bool check(int x,int y){//判断下一个位置是否合法
return x>=1&&y>=1&&x<=n&&y<=m&&maze[x][y]!='#';
}
void bfs(int a,int b,int c){
queue<pair<int,pair<int,int> > >q;
q.push(mp(a,mp(b,0)));
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)vis[i][j]=false;
vis[a][b]=true;//标记初始位置
while(!q.empty()){
int x=q.front().fi;
int y=q.front().se.fi;
int z=q.front().se.se;
q.pop();
if(step[x][y]==-1)step[x][y]=z;//第一遍时记录小A到达该位置的最短时间
else ans=min(ans,max(step[x][y],z));//否则如果该位置不为-1证明该位置小A和小B都可以走到,更新答案
for(int i=c==1?0:4;i<8;i++){
int nx=x+dir[i][0],ny=y+dir[i][1];//走一步的位置
if(c==2&&check(nx,ny)){//小B能走下一步的条件是先走第一步可以走到
if(step[nx][ny]!=-1){//如果先走一步时的位置小A可以走到
ans=min(ans,max(step[nx][ny],z+1));//更新答案
}
for(int j=4;j<8;j++){//否则对下一步进行判断
int nnx=nx+dir[j][0],nny=ny+dir[j][1];
if(check(nnx,nny)&&!vis[nnx][nny]){//符合条件加入队列
vis[nnx][nny]=1;
q.push(mp(nnx,mp(nny,z+1)));
}
}
continue;
}
if(!vis[nx][ny]&&check(nx,ny)){/小A的处理代码
vis[nx][ny]=1;
q.push(mp(nx,mp(ny,z+1)));
}
}
}
}
void solve(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>maze[i][j];
step[i][j]=-1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
if(maze[i][j]=='C')bx=i,by=j;
else if(maze[i][j]=='D')ex=i,ey=j;
}
bfs(bx,by,1);
bfs(ex,ey,2);
if(ans!=inf)printf("YES\n%d\n",ans);
else printf("NO\n");
}
int main(){
//int o;scanf("%d",&o);
//while(o--){
solve();
//}
return 0;
}

京公网安备 11010502036488号