hdu-3085(双向bfs)

来源:互联网 发布:linux暴力破解root密码 编辑:程序博客网 时间:2024/05/16 14:49

题目大意:
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;                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;}