ch2(搜索与图论)——双向广搜

1.自然语言描述
当状态空间树很大很大时(时间复杂度很高)从起点到终点直接BFS仍会超时;可以考虑分别从起点和终点双向BFS,双向BFS会将原来的状态空间树极大地缩小。

双向BFS的扩展方式:既然是双向BFS,则起点开始和终点开始各需要一个活结点队列,最短路径的保存记录也需要两个——各自相对于起点和终点的最短路径记录。扩展时,优先扩展两个队列中活结点较少的那一侧。

2.代码描述
题目:Acwing 190.字串变换 题目链接

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#include <queue>

using namespace std;

const int MAXN=22;

string a[MAXN],b[MAXN];
int n,cnt;

int extend(queue<string> &qa,unordered_map<string,int> &da,unordered_map<string,int> &db,string a[],string b[])
{
    
    
    string t=qa.front();
    qa.pop();

    for(int i=0;i<(int)t.size();i++)
        for(int j=0;j<n;j++)
            if(t.substr(i,(int)a[j].size())==a[j]){
    
    
                string state=t.substr(0,i)+b[j]+t.substr(i+a[j].size());//拼起来
                if(db.count(state)) return da[t]+1+db[state];//state被对侧广搜搜到了,也就是双端广搜在此碰头
                //从本侧广搜起点到t的步数为da[t],对侧广搜起点到state的步数为db[state],t扩展到state距离为1
                else{
    
    
                    da[state]=da[t]+1;
                    qa.push(state);
                }
            }
    return 11;//没有相遇
}

int bfs(string A,string B)
{
    
    
    queue<string> qa,qb;
    unordered_map<string,int> da,db;
    qa.push(A),qb.push(B);
    da[A]=0;
    db[B]=0;

    while(!qa.empty()&&!qb.empty()){
    
    

        int t;
        if(qa.size()<=qb.size())//每次从活结点队列中元素较少的一侧扩展
            t=extend(qa,da,db,a,b);
        else
            t=extend(qb,db,da,b,a);

        if(t<=10) return t;
    }
    return 11;
}

int main(void)
{
    
    
    string A,B;
    cin>>A>>B;

    while(cin>>a[n]>>b[n]) n++;

    int cnt=bfs(A,B);
    if(cnt>10) cout<<"NO ANSWER!"<<endl;
    else cout<<cnt<<endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43579980/article/details/108956988