您的位置:首页 > 其它

hdu 3085(双向bfs)

2013-09-06 09:30 411 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085

思路:双向广搜,每次从M出发,搜三步,从G出发,搜一步,然后就是判断是否走到对方已经走过的格子,至于魔王的判断,可以用曼哈顿距离。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define MAXN 1000

struct Node{
int x,y;
Node(){}
Node(int xx,int yy):x(xx),y(yy){};
}mm,gg,zz[2];

bool mark[MAXN][MAXN][2];
int n,m,step;
char map[MAXN][MAXN];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
queue<pair<int,int> >que[2];

bool Judge(int x,int y)
{
if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='X'){
for(int i=0;i<2;i++){
if((abs(x-zz[i].x)+abs(y-zz[i].y))<=2*step)return false;
}
return true;
}
return false;
}

bool bfs(int num)
{
int size=que[num].size();
while(size--){
int x=que[num].front().first;
int y=que[num].front().second;
que[num].pop();
if(!Judge(x,y))continue;
for(int i=0;i<4;i++){
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(Judge(xx,yy)){
if(!mark[xx][yy][num]){
if(mark[xx][yy][num^1])return true;
mark[xx][yy][num]=true;
que[num].push(make_pair(xx,yy));
}
}
}
}
return false;
}

int Solve()
{
memset(mark,false,sizeof(mark));
while(!que[0].empty())que[0].pop();
while(!que[1].empty())que[1].pop();
que[0].push(make_pair(mm.x,mm.y));
que[1].push(make_pair(gg.x,gg.y));
mark[mm.x][mm.y][0]=mark[gg.x][gg.y][1]=true;
step=0;
while(!que[0].empty()||!que[1].empty()){
step++;
if(bfs(0))return step;//mm要搜三步
if(bfs(0))return step;
if(bfs(0))return step;
if(bfs(1))return step;
}
return -1;
}

int main()
{
int _case,index;
scanf("%d",&_case);
while(_case--){
scanf("%d%d",&n,&m);
index=0;
for(int i=0;i<n;i++){
scanf("%s",map[i]);
for(int j=0;j<m;j++){
if(map[i][j]=='M')mm=Node(i,j);
else if(map[i][j]=='G')gg=Node(i,j);
else if(map[i][j]=='Z')zz[index++]=Node(i,j);
}
}
printf("%d\n",Solve());
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: