一、算法分析
首先题目说若在10步之内有解就输出步数,十步之内无解就是NO ANSWER,这就说明了搜索的深度不会超过十步,可以考虑用迭代搜索。迭代深搜基本框架和数据的读入写好之后,就是处理细节了,刚开始打算用链表做,结果自不常用链表,一直写错,后来发现可以用string类里面的find函数和replace函数来解决题目中的替换问题,find函数的作用是在a串中找到b串第一次出现的地方,用法a.find(b) 。而replace可以将a串从第m位开始的len个字符替换成b串,用法a.replace(m,len,b)。然后就高高兴兴打出了代码,结果交上去只有80分,最后一个点WA。(没有进行任何剪枝操作,题目时限比较宽裕,居然没有一个点TLE)。先贴上80分代码。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
string st1;
string st2;
const int maxn=15;
int ok=0;
struct method{
string s1;
string s2;
}p[maxn];
string ss1,ss2;
int cnt;
int d; //迭代加深的深度
void dfs(int cur,string st){
if(cur>d) return; //因为dfs是同层同步的,所以只要有一个触底就全部触底,那么就说明d深度内无法找到答案
for(int i=1;i<=cnt;i++){ //尝试每种操作
string ss=st;
int m=ss.find(p[i].s1);
if(m==-1) continue;
int len=(p[i].s1).size();
ss.replace(m,len,p[i].s2);
if(ss==st2){
ok=1;
cout<<cur;
return;
}
if(!ok) dfs(cur+1,ss);
}
}
int main(){
cin>>st1>>st2; //读入
while(cin>>ss1>>ss2){
p[++cnt].s1=ss1;
p[cnt].s2=ss2;
}
for(d=1;d<=10 && !ok;d++){
dfs(1,st1);
}
if(!ok) cout<<"NO ANSWER!";
return 0;
}
然后就开始处理WA的点,搞了半天发现这个写法存在的问题在于忽略了同一种操作可能会在一个串中执行多次的可能,比如
aabbaaa这个串,如果变换规则中有aa ——> b ,那么这个串就可以有多个变换位点,而上面的代码只考虑了第一次出现的aa。所以就要对同一个规则执行多次find,然后改进代码之后又不对了,比如这个例子,find函数每次都找的是第一个出现的aa,最后只能死循环。百思不得其解之下查阅了一些其它题解,发现了find函数还有一个参数,可以规定查找从第几位开始,这样就可以记录下来m,每次查找从m+1开始,这样就避免了重复查找一个位置的情况。AC代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
string st1;
string st2;
const int maxn=15;
int ok=0;
struct method{
string s1;
string s2;
}p[maxn];
string ss1,ss2;
int cnt;
int d; //迭代加深的深度
void dfs(int cur,string st){
if(cur>d) return; //因为dfs是同层同步的,所以只要有一个触底就全部触底,那么就说明d深度内无法找到答案
for(int i=1;i<=cnt;i++){ //尝试每种操作
int m=-1;
while(true){
m=st.find(p[i].s1,m+1);
if(m==-1) break; //如果find返回-1则说明没有找到
string ss=st;
int len=(p[i].s1).size();
ss.replace(m,len,p[i].s2); //函数的用法和m的处理上面算法分析写得很清楚了,这里就不写了
if(ss==st2){
ok=1;
cout<<cur;
return;
}
if(!ok) dfs(cur+1,ss);
}
}
}
int main(){
cin>>st1>>st2; //读入
while(cin>>ss1>>ss2){
p[++cnt].s1=ss1;
p[cnt].s2=ss2;
}
for(d=1;d<=10 && !ok;d++){
dfs(1,st1);
}
if(!ok) cout<<"NO ANSWER!";
return 0;
}