POJ1915 双向广度优先搜索

来源:互联网 发布:软件人才缺口多少 编辑:程序博客网 时间:2024/06/08 04:26

双向广度优先搜索算法:初始状态(正向搜索)和目标状态(逆向搜索)同时向中间搜,当两个方向的搜索生成同一子状态时,搜索结束;一般用来解决最小等最优问题;

如何判断是否生成了同一子状态:(1)用标记数组,若某一状态未被遍历到,则为0,正向遍历到为1,逆向遍历到为2,当遍历到某一状态时,判断一下其对应标记数组的值;(2)本题(poj1915)代码;

#include<cstdio>#include<iostream>#include<queue>;using namespace std;#define Maxn 309struct node{    int x,y;};//坐标节点int n;//图的大小int fstep[Maxn][Maxn],bstep[Maxn][Maxn];//记录正向搜索和逆向搜索步数int dir[8][2] = {-1,-2,-2,-1,-2,1,-1,2,1,2,2,1,2,-1,1,-2};bool isok(node a){    if (a.x < 0 || a.x >= n || a.y < 0 || a.y >= n)        return false;    return true;}int BBFS(node a,node b){    if (a.x == b.x && a.y == b.y)    {        return 0;    }//如果起点和终点一样,则返回0    int i,j;    queue<node>q1,q2;    for (i = 0; i < n; ++i)    {        for (j = 0; j < n; ++j)            fstep[i][j] = bstep[i][j] = -1;    }//步数初始化    fstep[a.x][a.y] = 0;//起点步数=0    bstep[b.x][b.y] = 0;//终点步数=0    q1.push(a);    q2.push(b);    while (!q1.empty() && !q2.empty())    {        /*如果起点能够到达终点的话,那么两个队列是不可能为空的,如果有一个队列为空        表明某一方向的搜索已经无法再继续下去,无路可走了,换言之,也没有路可以走        到这里,说明起点与终点是不可达的,就可以结束搜索了*/        node tt,t1,t2;        if (!q1.empty())        {            t1 = q1.front();            q1.pop();            for (i = 0; i < 8; ++i)            {                tt.x = t1.x + dir[i][0];                tt.y = t1.y + dir[i][1];                if (isok(tt))                {                    if (fstep[tt.x][tt.y] == -1)                    {                        fstep[tt.x][tt.y] = fstep[t1.x][t1.y] + 1;                        q1.push(tt);                    }                    if (bstep[tt.x][tt.y] != -1)//判断是否生成了同一子状态                        return fstep[tt.x][tt.y] + bstep[tt.x][tt.y];                    //达到子状态的那一步上面已经走了,故返回值不需要再加一                }            }        }        if (!q2.empty())        {            t2 = q2.front();            q2.pop();            for (i = 0; i < 8; ++i)            {                tt.x = t2.x + dir[i][0];                tt.y = t2.y + dir[i][1];                if (isok(tt))                {                    if (bstep[tt.x][tt.y] == -1)                    {                        bstep[tt.x][tt.y] = bstep[t2.x][t2.y] + 1;                        q2.push(tt);                    }                    if (fstep[tt.x][tt.y] != -1)//判断是否生成了同一子状态                        return bstep[tt.x][tt.y] + fstep[tt.x][tt.y];                    //达到子状态的那一步上面已经走了,故返回值不需要再加一                }            }        }    }}int main(){    int t,ans;    struct node a,b;    while (~scanf("%d",&t))    {        while (t--)        {            scanf("%d",&n);            scanf("%d%d%d%d",&a.x,&a.y,&b.x,&b.y);            ans = BBFS(a,b);            printf("%d\n",ans);        }    }    return 0;}/*这题其实还可以再优化一下,就是入队列时,可以用一个标记数组判断一下该状态是否已经在队列里了只不过要用到两个标记数组分别判断,这样写的话,代码感觉有点乱,反正能过,就算了,知道就行*/

0 0
原创粉丝点击