[NOIP2002] 字串变换

[问题描述]

已知有两个字串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 }
code

 

转载于:https://www.cnblogs.com/A-LEAF/p/7327739.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值