返回顶部

双向BFS

双向BFS

LuoguP1032 字串变换

引入

如果我们直接BFS,最坏情况下搜索空间是K10,采用双向BFS则可以把搜索空间降至2K5,而且剪枝效果相当不错。

思路

  1. 建立两个队列qa,qb,分别从起点和终点开始搜索,两边轮流进行拓展,每次都拓展一层。

  2. 每次拓展后比较一下两颗BFS树,优先拓展当前层状态树最小的那一颗,以便于控制每一棵树的宽度。

  3. 建立两个哈希表da,db,存储从树根到当前串的操作步数,并用哈希表去重。在BFS过程中,如果发现新串同时出现在另一个哈希表中,说明两棵树会合了,返回操作步数。

#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;

const int N=7;
int n;
string A,B,a[N],b[N];

int extend(queue<string>&q, unordered_map<string,int>&da,
    unordered_map<string,int>&db, string a[], string b[]){
  int m=q.size(); 
  while(m--){                       //每次扩展一层
    auto f=q.front(); q.pop();      //父串出队
    for(int i=0; i<n; i++)          //枚举规则
      for(int j=0; j<f.size(); j++) //枚举父串中的位置
        if(f.substr(j,a[i].size())==a[i]){
          string s=f.substr(0,j)+b[i]+f.substr(j+a[i].size());
          if(da.count(s)) continue;
          if(db.count(s)) return da[f]+db[s]+1;
          da[s]=da[f]+1;  //变换步数
          q.push(s);      //子串入队
        }
  }
  return 11;
}
int bfs(){
  if(A==B) return 0;
  queue<string> qa,qb;
  unordered_map<string,int> da,db;
  qa.push(A),qb.push(B); da[A]=db[B]=0;
  
  int step=10, t;
  while(step--){
    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(){
  cin>>A>>B;
  while(cin>>a[n]>>b[n]) n++;
  int t=bfs();
  t==11?printf("NO ANSWER!"):printf("%d",t);
}
posted @   supperwriter  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示