【题解】P1032 字串变换
题面
前言
字符串简单处理 + 迭代加深搜索
正文
本题一眼搜索
题解区好像都是广搜(或者 meet in the middle 之类的)
云落不大喜欢 BFS,所有我们选择 DFS
题意要求我们去求一个最小变换次数,即搜索树上的最小深度
很容易想到迭代加深搜索
若干个难点:
-
区别于朴素的迭代加深搜索,这个题的状态拓展是在字符串上进行的,所以与状态相关的信息的存储需要由数组转化为映射,云落使用的
map
,(手写哈希也可嗷!) -
剪枝优化
-
迭代加深搜索自行控制深度——可行性剪枝
-
当字符串相同时,停止搜索,记录答案最小值——边界条件(最优性剪枝)
-
当一个状态已经被访问过,且当前答案不优于已有的答案,直接减掉——最优性剪枝
- 状态拓展
-
若干个字符串操作
-
请注意:
find
函数只能找到一个合法的子串,我们需要人为规定一下找子串的范围
- 迭代加深终止条件:
if(ans!=inf)break;
代码
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=8,inf=2147483647;
string A,B;
struct Edge{
string u,v;
}e[maxn];
int tot=1,ans=inf,dep=2;
map<string,bool> vis;
map<string,int> dis;
inline void dfs(string str,int stp){
if(stp>dep){
return;
}
if(str==B){
ans=min(ans,stp);
return;
}
if(vis[str]){
if(stp>=dis[str]){
return;
}
}
vis[str]=true;
dis[str]=stp;
for(int i=1;i<=tot;i++){
int idx=-1;
while(true){
idx=str.find(e[i].u,idx+1);
if(idx==-1){
break;
}
string tmp=str;
tmp.erase(idx,e[i].u.length());
tmp.insert(idx,e[i].v);
dfs(tmp,stp+1);
}
}
return;
}
int main(){
cin>>A>>B;
while(cin>>e[tot].u>>e[tot].v){
tot++;
}
tot--;
while(true){
if(ans!=inf){
break;
}
dfs(A,0);
dis.clear();
vis.clear();
dep++;
if(dep==11){
break;
}
}
if(ans==inf){
cout<<"NO ANSWER!"<<endl;
return 0;
}
cout<<ans<<endl;
return 0;
}
后记
哎,居然是个绿题,稍稍恶心了一下下呢!
完结撒花!