自己写的时候先用BFS跑了一遍B能走到的所有位置,标记了所需的步数,然后再对A跑一边BFS,遇到B可以到的点便判断一下两个人如果在此相遇要多久,应该是两个人到该点所花时间较大的那个,记录这个结果。下一个A、B同时能到的点所花时间和当前的ans比较,选择小的那个。最后如果没有相遇点输出NO。
想了一下自己写的,不管是什么情况,都要把A和B能走的点都走一遍,复杂度O(NM),但是自己的代码只过了80%的样例,不知道还有哪里会出问题。
标程给的是两个方向的BFS同时跑,一次往外跑一层,只要相遇了,当前相遇点一定是时间最短的点。
80%样例代码:(如果有大神能指点一下哪里出了错就好了)
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3fffffff;
int dira[8][2]={{1,0},{0,1},{-1,0},{0,-1},{1,-1},{-1,1},{1,1},{-1,-1}};
int dirb[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
char mp[1010][1010];
int visa[1010][1010];
int visb[1010][1010];
struct node{
int x,y;
};
struct node2{
int x,y,t;
};
bool flag;
int ans;
int n,m;
void bfsb(node2 a){
queue<node2> q;
q.push(a);
while(!q.empty()){
node2 now=q.front();
q.pop();
for(int i = 0 ; i < 4 ; i ++){
int tx=now.x+dirb[i][0];
int ty=now.y+dirb[i][1];
int t=now.t;
if(visb[tx][ty] || mp[tx][ty]=='#' || tx<0 || tx>=n || ty<0 || ty>=m)
continue;
mp[tx][ty]='D';
if(t%2==0){//步数要加一
visb[tx][ty]=visb[now.x][now.y]+1;
}//步数不变
else visb[tx][ty]=visb[now.x][now.y];
t++;
node2 temp;
temp.t=t,temp.x=tx,temp.y=ty;
q.push(temp);
}
}
}
void bfsa(node a){
queue<node> q;
q.push(a);
while(!q.empty()){
node now=q.front();
q.pop();
for(int i = 0 ; i < 8 ; i ++){
int tx=now.x+dira[i][0];
int ty=now.y+dira[i][1];
if(visa[tx][ty]!=0 || mp[tx][ty]=='#' || tx<0 || tx>=n || ty<0 || ty>=m)
continue;
node temp={tx,ty};
visa[tx][ty]=visa[now.x][now.y]+1;
if(mp[tx][ty]=='D'){
flag=true;
int res=max(visa[tx][ty],visb[tx][ty]);
ans=min(ans,res-1);
}
q.push(temp);
}
}
}
int main(){
// freopen("in.txt","r",stdin);
node A;
node2 B;
cin>>n>>m;
for(int i = 0 ; i < n ; i ++){
for(int j = 0 ; j < m ; j ++){
cin>>mp[i][j];
visa[i][j]=visb[i][j]=0;
if(mp[i][j]=='C') A.x=i,A.y=j;
if(mp[i][j]=='D') B.x=i,B.y=j,B.t=1;
}
}
flag=false;
ans=INF;
visb[B.x][B.y]=1;//原点算了一步
bfsb(B);
visa[A.x][A.y]=1;//原点算了一步
bfsa(A);
// cout<<"**************"<<endl;
// for(int i = 0 ; i < n ; i ++){
// for(int j = 0 ; j < m ; j ++){
// cout<<mp[i][j]<<' ';
// }
// cout<<endl;
// }
// cout<<"**************"<<endl;
// for(int i = 0 ; i < n ; i ++){
// for(int j = 0 ; j < m ; j ++){
// cout<<visb[i][j]<<' ';
// }
// cout<<endl;
// }
// cout<<"**************"<<endl;
// for(int i = 0 ; i < n ; i ++){
// for(int j = 0 ; j < m ; j ++){
// cout<<visa[i][j]<<' ';
// }
// cout<<endl;
// }
if(flag){
cout<<"YES\n"<<ans;
}
else cout<<"NO";
return 0;
}
AC代码:
#include<bits/stdc++.h>
using namespace std;
bool vis[2][1010][1010];
char mp[1010][1010];
int dirx[8]={0,0,1,-1,1,1,-1,-1};
int diry[8]={1,-1,0,0,1,-1,1,-1};
int n,m;
int cx,cy,dx,dy;
struct node{
int x,y;
};
queue<node> q[2];
int bfs(int w){//w表示是A在走还是B在走
int sz=q[w].size();
while(sz--){
node now=q[w].front();
q[w].pop();
for(int i = 0 ; i < 4+(w==0?4:0) ; i++){
int tx=now.x+dirx[i];
int ty=now.y+diry[i];
if(mp[tx][ty]=='#' || tx<0 || tx>=n || ty<0 || ty>=m)
continue;
if(!vis[w][tx][ty]){
if(vis[w^1][tx][ty]) return 1;//异或1取反
vis[w][tx][ty]=1;
q[w].push({tx,ty});
}
}
}
return 0;
}
int solve(){
q[0].push({cx,cy});
q[1].push({dx,dy});
vis[0][cx][cy]=vis[1][dx][dy]=1;
int step=0;
while(!q[0].empty() || !q[1].empty()){
step++;
if(bfs(0)) return step;//A走一次
if(bfs(1)) return step;//B可以走两次
if(bfs(1)) return step;
}
return -1;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i = 0 ; i < n ; i ++){
for(int j = 0 ; j < m ; j ++){
cin>>mp[i][j];
if(mp[i][j]=='C') cx=i,cy=j;
if(mp[i][j]=='D') dx=i,dy=j;
}
}
int ans=solve();
if(ans==-1) cout<<"NO";
else cout<<"YES\n"<<ans;
return 0;
}