可以理解为两个人同时走迷宫,走到同一地方时最少的步数,那么可以开两个队列,每次都各自扩展一层,若遇到自己可以走到的地方,另一个人走到了,那么说明这个地方就是最小的步数处。
给一道题:https://ac.nowcoder.com/acm/contest/549/G
A:每次可以向八个方向走一步;B:每次可以从四个方向选,可以走两步。
那么每次可以考虑为为A扩展一层,为B扩展两次一层,即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e3+7;
char mapp[maxn][maxn];
bool vis[2][maxn][maxn];//0为A,1为B
int n,m;
bool check(int w,int x,int y){
if(x>=0&&x<n&&y>=0&&y<m&&mapp[x][y]!='#'&&vis[w][x][y]==0) return 1;
return 0;
}
struct Node{
int x,y;
}in,out,st1,st2;
queue<Node> q[2];
int dx[8]={0,0,1,-1,1,-1,1,-1};
int dy[8]={-1,1,0,0,1,-1,-1,1};
bool bfs(int w){
int t=q[w].size();
while(t--){
out=q[w].front(); q[w].pop();
for(int i=0;i<(w?4:8);++i){
int x=dx[i]+out.x;
int y=dy[i]+out.y;
if(check(w,x,y)){
if(vis[w^1][x][y]) return 1;
vis[w][x][y]=1;
in.x=x,in.y=y;
q[w].push(in);
}
}
}
return 0;
}
int getstep(){
q[0].push(st1);
q[1].push(st2);
vis[0][st1.x][st1.y]=vis[1][st2.x][st2.y]=1;
int res=0;
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;
}
char s[3];
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;++i)
for(int j=0;j<m;++j){
scanf("%s",s);
mapp[i][j]=s[0];
if(s[0]=='C'){
st1.x=i,st1.y=j;
mapp[i][j]='.';
}
if(s[0]=='D'){
st2.x=i,st2.y=j;
mapp[i][j]='.';
}
}
int res=getstep();
if(res==-1) printf("NO\n");
else printf("YES\n%d\n",res);
return 0;
}