题目描述
已知有两个字串 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!"
输入输出样例
输入样例#1:
abcd xyz
abc xu
ud y
y yz
输出样例#1:
3
Solution:
先看一波STL之string详解
然后本题直接搜嘛,广搜可以,深搜也行,还可以迭代深搜,我用的是dfs。思路比较简单,先用map建立一个string到int的映射,然后对每种变化方式不断在原字符串中查找出现的位置,并进行变化继续深搜。然后就是对于步数超过10的直接剪枝(注意ans不超过10),再加入一条可行性剪枝用最少或最多的变换在剩余的不超过10步的步数中依然大于或无法达到目标字符串的长度,直接减枝,最后输出map映射的目标串的步数就ok咯。
代码:
#include<bits/stdc++.h> #define il inline #define ll long long #define debug printf("%d %s\n",__LINE__,__FUNCTION__) using namespace std; const int mod = 998244353; string s,e,a[20],b[20]; int lena[20],lenb[20],cnt=1,mx=0,mn=0; map<string,int>m; il void dfs(string x,int k){ //debug; if(k>=10)return; int v=x.size(),p=e.size(); if((v+mx*(10-k)<p)||(v+mn*(10-k)>p))return; k++; for(int i=1;i<=cnt;i++){ int pos=x.find(a[i],0); while(pos!=string::npos){ string tmp=x; tmp.replace(pos,lena[i],b[i]); if((!m[tmp]&&tmp!=s)||(m[tmp]>m[x]+1)) m[tmp]=m[x]+1,dfs(tmp,k); pos=x.find(a[i],pos+1); } } } int main() { ios::sync_with_stdio(0); cin>>s>>e; while(cin>>a[cnt]>>b[cnt]){ lena[cnt]=a[cnt].size(); lenb[cnt]=b[cnt].size(); mn=min(mn,lenb[cnt]-lena[cnt]); mx=max(mx,lenb[cnt]-lena[cnt]); cnt++; if(cnt>6)break; } cnt--; dfs(s,0); if(m[e])cout<<m[e]; else cout<<"NO ANSWER!"; return 0; }