【双向广搜】 字串变换

传送门

题意

给定字符串\(A、B\),给定串\(A\)的变换规则,问能否通过10次变换内将\(A\)变成\(B\)

数据范围

\(1\leq |A|、|B|\leq 20\)

题解

两个队列分别是从起始向终点搜和反向搜索

  • 每次都从当前层数少的进行扩展,实际运行下较优
  • \(substr(int \;i,int\; j)\)函数表示的是从\(i\)开始长度为\(j\)的子串
  • \(unordered\_map\)记录距离以及是否搜索到

Code

#include<bits/stdc++.h>
using namespace std;
#define ump unordered_map
string a[7],b[7];
int n;
int extend(queue<string>&q,ump<string,int>&dst,ump<string,int>&ded,string a[],string b[]){
    // 每次扩展当前一层节点
    for(int k=0,lk=q.size();k<lk;k++){
        string t=q.front();
        q.pop();

        for(int i=0;i<t.size();i++)
            for(int j=0;j<n;j++){
                if(t.substr(i,a[j].size()) == a[j]){
                    string now=t.substr(0,i)+b[j]+t.substr(i+a[j].size()); // substr 只有起点时为起点到终点

                    if(dst.count(now)) continue; // 已经入队
                    if(ded.count(now)) return dst[t]+ded[now]+1;
                    dst[now]=dst[t]+1;
                    q.push(now);
                }
            }
    }
    return 11;
}
int bfs(string A,string B){
    queue<string>qst,qed;
    ump<string,int>dst,ded;
    qst.push(A);qed.push(B);
    dst[A]=0;ded[B]=0;
    while(qst.size() && qed.size()){
        int t;
        if(qst.size()<=qed.size()) t=extend(qst,dst,ded,a,b);
        else t=extend(qed,ded,dst,b,a);
        if(t<=10) return t;
    }
    return 11;
}
int main(){
    string A,B;
    cin>>A>>B;
    while(cin>>a[n]>>b[n]) n++;
    int step=bfs(A,B);
    if(step > 10) cout<<"NO ANSWER!"<<endl;
    else cout<<step<<endl;
    return 0;
}
posted @ 2020-11-03 11:09  Hyx'  阅读(62)  评论(0编辑  收藏  举报