【HDU3085】nightmare2 双向BFS

对于搜索树分支很多且有明确起点和终点的情况时,可以采用双向搜索来减小搜索树的大小。

对于双向BFS来说,与单向最大的不同是双向BFS需要按层扩展,表示可能到达的区域。而单向BFS则是按照单个节点进行扩展,因为只有当前状态。

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn=810;

char mp[maxn][maxn];
int n,m,tot,step,f;
struct node{
    int x,y;
}boy,girl,ghost[2];
queue<node> q[2];//两个队列
bool vis[2][maxn][maxn];//两个表示可达性

void init(){
    tot=0;
    while(q[0].size())q[0].pop();
    while(q[1].size())q[1].pop();
    memset(vis,0,sizeof(vis));
}

void read_and_parse(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",mp[i]+1);
        for(int j=1;j<=m;j++){
            if(mp[i][j]==‘M‘)boy=(node){i,j};
            if(mp[i][j]==‘G‘)girl=(node){i,j};
            if(mp[i][j]==‘Z‘)ghost[tot++]=(node){i,j};
        }
    }
}

bool right(int x,int y){
    if(x<1||x>n||y<1||y>m||mp[x][y]==‘X‘)return 0;
    if(abs(x-ghost[0].x)+abs(y-ghost[0].y)<=step<<1)return 0;
    if(abs(x-ghost[1].x)+abs(y-ghost[1].y)<=step<<1)return 0;
    return 1;
}

const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};

bool bfs(int idx){
    int size=q[idx].size();
    while(size--){
        node now=q[idx].front();q[idx].pop();
        if(!right(now.x,now.y))continue;//查看当前状态是否合法

        for(int i=0;i<4;i++){
            int x=now.x+dx[i],y=now.y+dy[i];
            if(!right(x,y)||vis[idx][x][y])continue;
            if(vis[1-idx][x][y])return 1;
            vis[idx][x][y]=1;
            q[idx].push((node){x,y});
        }
    }
    return 0;
}

void solve(){
    step=0,f=0;
    q[0].push((node){boy.x,boy.y});
    q[1].push((node){girl.x,girl.y});

    while(q[0].size()||q[1].size()){
        ++step;
        for(int i=1;i<=3;i++)if(bfs(0)){f=1;break;}//每次扩展三层,表示走三步可能到达的状态
        if(bfs(1)){f=1;break;}
    }

    if(f)printf("%d\n",step);
    else puts("-1");
}

int main(){
    int T;scanf("%d",&T);
    while(T--){
        init();
        read_and_parse();
        solve();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/wzj-xhjbk/p/9800893.html

时间: 2024-10-11 17:43:45

【HDU3085】nightmare2 双向BFS的相关文章

HDU3085 Nightmare Ⅱ (双向BFS)

联赛前该练什么?DP,树型,状压当然是爆搜啦 双向BFS就是两个普通BFS通过一拼接函数联系,多多判断啦 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define R(a,b,c) for(register int a = (b); a <= (c); ++a) #define nR(a,b,c

Hdu1401-Solitaire(双向bfs)

Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered from 1 to 8, from the top to the bottom and from left to right respectively.There are four identical pieces on the board. In one move it is allowed to

UVA-1604 Cubic Eight-Puzzle (双向BFS+状态压缩+限制搜索层数)

题目大意:立体的八数码问题,一次操作是滚动一次方块,问从初始状态到目标状态的最少滚动次数. 题目分析:这道题已知初始状态和目标状态,且又状态数目庞大,适宜用双向BFS.每个小方块有6种状态,整个大方格有9*6^8个状态.每个小方块用一位6进制数表示即可. 注意:状态转移时要谨慎,否则会出现意想不到的错误: 这道题的末状态有256(2^8)个,如果对搜索层数不加限制,即使双向BFS也会TLE的,当限制正向搜索15层逆向搜索15层至正向搜索27层反向搜索3层时都能AC(我下面贴出的程序是这样的),其

HDU1195 双向BFS(或BFS)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1195 , 双向BFS或者直接BFS也可以过. 其实这道题只是单向BFS就可以过的,但是为了练算法,所以还是用了双向BFS来写. 算法: 先预处理一下,从1111到9999的所有点进行构图(由于是1~9的,所以除去含有0元素的数字),能进行一次变换变成的数字则表示两点之间连通.然后从初态与目态两个点进行BFS,如果有轨迹重合的就返回路程和. 这里注意双向BFS要一层一层的进行搜索,不然的话会产生错误,

POJ1915Knight Moves(单向BFS + 双向BFS)

题目链接 单向bfs就是水题 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int INF = 0x3f3f3f3f; 8 const int Max = 300 + 5; 9 struct Node 10 { 11 int

BFS、双向BFS和A*

BFS.双向BFS和A* Table of Contents 1. BFS 2. 双向BFS 3. A*算法 光说不练是无用的.我们从广为人知的POJ 2243这道题谈起:题目大意:给定一个起点和一个终点.按骑士的走法(走日字),从起点到终点的最少移动多少次 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2RraXJjaGhvZmY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/g

HDU 1043 Eight(双向BFS+康托展开)

http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用双向BFS来做. ①双向BFS 在单向BFS的基础上,多建一个从终止状态开始搜索的队列,当然这个时候需要两个vis[]辅助数组,分别记录两个队列的访问情况,当两个队列相遇时即可终止循环. ②康托展开 X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[

POJ 1915-Knight Moves (单向BFS &amp;&amp; 双向BFS 比较)

题目链接:Knight Moves 研究了一下双向BFS,不是很难,和普通的BFS一样,双向BFS不过是从 起点和终点同时开始搜索,可减少搜索时间 当两条搜索路线相遇时,结束. 貌似有一年百度的招聘 笔试,就是双向BFS.... 下面,比较一下BFS 和 双向BFS的用时: BFS STL的queue可能会浪费一点时间 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstrin

第六章部分例题 双向bfs邻接表和邻接矩阵实现

Idealpath 双向bfs输出颜色,邻接矩阵实现 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <map> 6 #include <algorithm> 7 8 using namespace std; 9 10 const int maxn=10000; 11 const int inf=1