题意:
给出一张地图和小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; }