双向宽度搜索

双向宽度搜索

  从正反两个方向进行宽度优先搜搜,可以大大减少搜索量,提高搜索速度。

  从初始状态和目标状态两个方向同时进行扩展,如果两颗解答树在某个节点第一次发生重合,即可终止此搜索过程,则该节点所连接的两条路径所拼成的路径就是最优解。

搜索方式

通常有两种搜索方式

1.两个方向交替扩展

2.选择节点个数较少的那个方向先扩展

方法2只需要略加修改控制结构,每次while循环时只扩展正反两个方向中节点数目较少的那一个,可以使两边的发展速度保持一定的平衡,从而减少总扩展节点的个数,加快搜索速度。

很明显,方法2优于方法1

code

int head[2],tail[2],ans;
struct s{int x,y;} q[2][maxn];//队列
int v[2][maxn][maxn];//记录访问节点的数组
int dis[2][maxn][maxn];//寻找最短路径时记录数组 
int dx[10],dy[10];//扩展方向
int expand(int k)//对k队列进行扩展
{
    int h,t,d,x,y;

    x=q[k][head[k]].x;
    y=q[k][head[k]].y;
    d=dis[k][x][y];
    for(int i=0;i<8;++i)
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(judge()&&!v[k][nx][ny])
        {
            v[k][nx][ny]=1;
            tail[k]++;
            q[k][tail[k]].x=nx;
            q[k][tail[k]].y=ny;
            dis[k][nx][ny]=d+1;
            if(v[k^1][nx][ny])
            {
                ans=dis[k][nx][ny]+dis[k^1][nx][ny];
                return 1;//找到了 
            }
        }
    }
    return 0;
}
void BFS()
{
    q[0][1]
    //这里特判一下是不是起点等于终点
    if(judge()){ans=0; return;}
    q[0][1].x=startx; q[0][1].y=starty;
    q[1][1].x=endx; q[1][1].y=endy;
    v[0][q[0][1].x][q[0][1].y]=1;
    v[1][q[1][1].x][q[1][1].y]=1;
    tail[0]=head[0]=tail[1]=head[1]=1;
    while(head[0]<=tail[0]&&head[1]<=tail[1])
    {
        if(tail[0]-head[0]<tail[1]-head[1])
        {
            expand(0);
            head[0]++;
        }
        else
        {
            expand(1);
            head[1]++;
        }
        //方法二,择优扩展 
    }
    return;
}

这种包装的暴力也就我这种不会正解蒟蒻用吧

原文地址:https://www.cnblogs.com/Liuz8848/p/10419920.html