HDU3085_Nightmare Ⅱ_双向BFS

来源:互联网 发布:朱宸慧淘宝店经历 编辑:程序博客网 时间:2024/06/08 11:31

题意

在一个迷宫里,有一个boy和一个girl,还有两个鬼。boy每秒钟走 3 步,girl 每秒钟走 1 步,鬼每秒钟超两步内能到达的格内分身。注意,鬼可以无视墙壁。并且, 每一秒,鬼分裂boy和girl再走。如果boy或girl和鬼在一个格子里,它们会被吃掉。问在被吃掉之前boy和girl能否相遇。

思路

一开始想的是 预处理+BFS。就是先把 鬼 和 boy 到达每个点的时间求出来,然后对 girl BFS。果不其然,TLE。这个题是 双向BFS。

1.从 boy 和 girl 两个点出发,双向BFS。
2.不需要对 鬼 进行预处理,只需在到达每个点是判断点到鬼的距离即可,O(1)。
3.需要注意的一点是,输入的时候如果一个字符一个字符地读会TLE,一行一行地读就AC了。

双向DFS

其实双向dfs就是把 队列 和 dis 数组都搞成二维的,对应每一方向。然后把起点和终点分别放进一个队列里,当两个队列出现重合点时,搜索就结束了。
双向DFS较单向有很大幅度的效率提升。

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=3085

AC代码

#include<cstdio>#include<iostream>#include<cstring>#include<queue>using namespace std;typedef pair<int, int> P;const int maxn = 810;const int  inf = 0x3f3f3f3f;const int mx[4] = {-1, 0, 1, 0};const int my[4] = {0, 1, 0, -1};int cas;int n, m;char G[maxn][maxn];P M, W, Z0, Z1;bool dis[2][maxn][maxn];queue<P> qu[2];int Abs(int x){    return x > 0 ? x : -x;}//检查点是不是安全bool check(int x, int y, int steps){    if(x < 0 || x >= n || y < 0 || y >= m) return false;    if(G[x][y] == 'X') return false;    //和鬼的距离    if(Abs(x - Z0.first) + Abs(y - Z0.second) <= 2 * steps) return false;    if(Abs(x - Z1.first) + Abs(y - Z1.second) <= 2 * steps) return false;    return true;}//u 是队列序号,steps 是时间bool bfs(int u, int steps){    int num = qu[u].size();//这一点学到了    while(num --)    {        int x = qu[u].front().first, y = qu[u].front().second;        qu[u].pop();        if(!check(x, y, steps)) continue;//因为鬼先走,所以这里还要检查一次        for(int i= 0; i< 4; i++)        {            int xx = x + mx[i], yy = y + my[i];            if(!dis[u][xx][yy] && check(xx, yy, steps))            {                if(dis[u^1][xx][yy]) return true;//会师成功                dis[u][xx][yy] = true;                qu[u].push(P(xx, yy));            }        }    }    return false;}int bid_bfs(){    //初始化    memset(dis, false, sizeof dis);    while(qu[0].size()) qu[0].pop();    while(qu[1].size()) qu[1].pop();    //两个起点各自入队    dis[0][M.first][M.second] = true;    qu[0].push(M);    dis[1][W.first][W.second] = true;    qu[1].push(W);    //boy 走三步,girl 走一步    for(int i= 1; qu[0].size() || qu[1].size(); i++)    {        if(bfs(0, i)) return i;        if(bfs(0, i)) return i;        if(bfs(0, i)) return i;        if(bfs(1, i)) return i;    }    //不能会师    return -1;}int main(){    cin >> cas;    while(cas --)    {        scanf("%d %d", &n, &m);        for(int i= 0; i< n; i++)            scanf(" %s", &G[i]);        Z0.first = -1;        for(int i= 0; i< n; i++)            for(int j= 0; j< m; j++)        {            if(G[i][j] == 'M') M = P(i, j);            if(G[i][j] == 'G') W = P(i, j);            if(G[i][j] == 'Z')                if(Z0.first == -1) Z0 = P(i, j);                else Z1 = P(i, j);        }        cout << bid_bfs() << endl;    }    return 0;}
原创粉丝点击