[问题描述]
已知有两个字串A$, B$及一组字串变换的规则(至多6个规则):
A1$ -> B1$
A2$ -> B2$
规则的含义为:在A$中的子串A1$可以变换为B1$、A2$可以变换为B2$…。
例如:A$='abcd' B$='xyz'
变换规则为:‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’
则此时,A$可以经过一系列的变换变为B$,其变换的过程为:
‘abcd’->‘xud’->‘xy’->‘xyz’
共进行了三次变换,使得A$变换为B$。
[输入]
A$ B$
A1$ B1$
A2$ B2$ |->变换规则
... ... /
所有字符串长度的上限为20。
[输出]
若在10步(包含10步)以内能将A$变换为B$,则输出最少的变换步数;否则输出"NO ANSWER!"
[输入样例]
abcd xyz
abc xu
ud y
y yz
[输出样例]
3
solution
不能用dfs,要用bfs,而且是双向bfs,用map<string,int>来记录当前串出现时走的步数以及是否出现
剪枝:如果此串已出现过,则不用再push如队列
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<string> 5 #include<queue> 6 #include<map> 7 using namespace std; 8 const int N=301; 9 int minn(int a,int b){return a<b?a:b;} 10 11 struct son 12 { 13 string s; 14 int bushu; 15 son(string qq,int ww) 16 { 17 s=qq;bushu=ww; 18 } 19 }; 20 int cnt,ans=1000; 21 string a,b,a1[8],b1[8]; 22 map<string,int> mpa,mpb; 23 queue<son> qa,qb; 24 25 int fin(string a,int pos,string s,int lena,int lens) 26 { 27 for(int i=pos;i<lena-lens+1;++i) 28 if(a[i]==s[i-pos]) 29 { 30 int flag=0; 31 for(int j=0;j<lens;++j) 32 if(s[j]!=s[j+i]) 33 {flag=1;break;} 34 if(flag)continue; 35 return i; 36 } 37 return -1; 38 } 39 40 int bfs() 41 { 42 mpa[a]=0;mpb[b]=0; 43 qa.push(son(a,0));qb.push(son(b,0)); 44 string temp; 45 while(!qa.empty()&&!qb.empty()) 46 { 47 son now=qa.front();qa.pop(); 48 string s=now.s; 49 50 //cout<<s<<endl; 51 if(now.bushu<=10) 52 { 53 if(mpb.count(s)) 54 ans=minn(ans,mpb[s]+now.bushu); 55 int len=s.size(); 56 for(int i=1;i<=cnt;++i) 57 { 58 int lent=a1[i].size(); 59 for(int j=0;j<len-lent+1;++j) 60 { 61 if(s.find(a1[i],j)==string::npos)break; 62 j=s.find(a1[i],j); 63 temp=s; 64 s.replace(j,lent,b1[i]); 65 //printf("pushas= "); 66 //cout<<s<<endl; 67 if(!mpa.count(s)) 68 { 69 mpa[s]=now.bushu+1; 70 qa.push(son(s,now.bushu+1)); 71 } 72 s=temp; 73 } 74 } 75 } 76 77 now=qb.front();qb.pop(); 78 s=now.s; 79 80 //cout<<s<<endl; 81 82 if(now.bushu<=10) 83 { 84 if(mpa.count(s)) 85 ans=minn(ans,mpa[s]+now.bushu); 86 int len=s.size(); 87 for(int i=1;i<=cnt;++i) 88 { 89 int lent=b1[i].size(); 90 for(int j=0;j<len-lent+1;++j) 91 { 92 /*int pos=fin(s,j,b1[i],len,lent); 93 if(pos==-1)break;*/ 94 if(s.find(b1[i],j)==string::npos)break; 95 j=s.find(b1[i],j); 96 temp=s; 97 //printf("pos=%d lent=%d\n",pos,lent); 98 //cout<<a1[i]<<endl; 99 //cout<<s<<endl; 100 s.replace(j,lent,a1[i]); 101 //cout<<s<<endl; 102 //printf("pushbs= "); 103 ///cout<<s<<endl; 104 if(!mpb.count(s)) 105 { 106 mpb[s]=now.bushu+1; 107 qb.push(son(s,now.bushu+1)); 108 } 109 s=temp; 110 } 111 } 112 } 113 114 } 115 if(ans<=10)return 1; 116 return 0; 117 } 118 119 int main(){ 120 //freopen("1.txt","r",stdin); 121 //freopen("string.in","r",stdin); 122 //freopen("string.out","w",stdout); 123 124 cin>>a>>b; 125 ++cnt; 126 while(cin>>a1[cnt]) 127 { 128 cin>>b1[cnt]; 129 ++cnt; 130 } 131 --cnt; 132 133 //printf("cnt=%d\n",cnt); 134 135 if(bfs()) 136 printf("%d",ans); 137 else 138 printf("NO ANSWER!"); 139 //while(1); 140 return 0; 141 }