您的位置:首页 > 其它

hdu-3085(双向bfs)

2017-05-17 20:36 393 查看
题目大意:

ghosts先每次分裂会覆盖两步之内所有的地方,然后erriyue每次走三步,girl friend每次走一步,ghosts能穿墙,人不能,问erriyue和girl friend是否能在指定的时间内相遇。

特别要注意的是,可以选择不走!不是一定要在那个时刻相遇! 英语渣,没读出来,但看别人的代码又确实是这个意思。

我一开始打算让幽灵也bfs,觉得这样不好写,搜网上有人用曼哈顿距离做,学习了一发。

比如说图上的两个黑点,分别表示当前的“我”(可以是erriyue,也可以是girl friend)和幽灵的初始位置,红蓝黄线都可以表示我到幽灵的曼哈顿距离,因为幽灵每次可以走两步,所以只要我到幽灵的曼哈顿距离小于二倍的已经走的次数,我就不会和幽灵相遇。



至于双向bfs我觉得和单向的区别不大,就是要注意交替逐层搜索,每次搜完都要判断一下。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;

const int tox[] = {0,1,0,-1};
const int toy[] = {1,0,-1,0};
char str[805][805];
int used[2][805][805];
int n,m,step;

struct node
{
int x,y;
} err,gf,z[2]; //分别表示初末位置,和两个小鬼的位置

queue<node> q[2];

void init()
{
int cnt=0;
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
{
scanf("%s",str[i]);
for(int j=0; j<m; j++)
{
if(str[i][j] =='M') //记录初末位置
{
err.x = i;

4000
err.y = j;
}
else if(str[i][j] =='G')
{
gf.x = i;
gf.y = j;
}
else if(str[i][j] =='Z')
{
z[cnt].x = i;
z[cnt++].y = j; //下次是第二个小鬼
}
}
}
}

int judge(node b)
{
if(b.x<0 || b.y<0 || b.x>=n || b.y>=m || str[b.x][b.y] =='X')
return 0;
if((abs(b.x-z[0].x) + abs(b.y-z[0].y)) <= 2*step)
return 0;
if((abs(b.x-z[1].x) + abs(b.y-z[1].y)) <= 2*step) //用曼哈顿距离表示 是否会碰到分裂的小鬼
return 0;
return 1;
}

int bfs(int w)
{
node one,next;
int sum;
sum = q[w].size();
while(sum--)
{
one = q[w].front();
q[w].pop();
if(judge(one) == 1)
{
for(int i=0; i<4; i++)
{
next.x = one.x + tox[i];
next.y = one.y + toy[i];
if(judge(next) == 0)
continue;
if(used[w][next.x][next.y] == 0)
{
if(used[w^1][next.x][next.y] == 1) //位运算w=0,这里就是1,w=1,这里就是0,判断两个人遇到了没
return 1;
used[w][next.x][next.y] = 1;
q[w].push(next);
}
}
}
}
return 0;
}
int solve()
{
while(!q[0].empty())
q[0].pop();
while(!q[1].empty())
q[1].pop();

q[0].push(err);
q[1].push(gf);
memset(used,0,sizeof(used));
used[0][err.x][err.y]=used[1][gf.x][gf.y]=1;
step=0;

while ((!q[0].empty()) || (!q[1].empty()))
{
step++;
if (bfs(0)==1)
return step;
if (bfs(0)==1)
return step;
if (bfs(0)==1) //走三步
return step;
if (bfs(1)==1) //走一步
return step;
}
return -1;
}
int main()
{
int Case;
scanf("%d",&Case);
while (Case--)
{
init();
printf("%d\n",solve());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: