NOIP 2002 提高组 字串变换

题目描述

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

 

表示做题时感到了NOIP深深的恶意……

这道题并不容易用比较快的数据结构实现,比如我的字符数组强迫症和模拟队列强迫症就被压得很惨,直接被教做人

好在数据并不大,最多求十步,反复提交发现只有不到十种变换方式,所以还是可以用string和STL que的,如果数据大,强迫症真得被搞死

所以如果可以用string和STL que的话,这题还比较好解

主要思想是如果当前能够变换就进行变换,然后把变换过的放入队尾,什么时候对头是变换完成的就直接输出步数

但是会超时,所以需要剪枝,可能有的串先变换与后变换变出的串相同,所以一个串只需记录第一次出现的情况,后来的步数肯定比第一次的步数多,所以不要,可以用一个map实现,存储<string,bool>如果串出现了,就将bool变为1,蛮巧妙地就将重复的情况解决了

而替换字符串是重点,这就是为什么不用字符数组,因为字符串有函数,实在是好使,大杀器一样,这个函数叫做 .replace(a,len,b),有三个参数,大概用法就是将字符串a后的len位替换为字符串b,与字符串b的大小无关,就是说b多长都能塞到len大小的空当里

上代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #include<map>
 6 using namespace std;
 7 int way=1;
 8 string start,end,a[11],b[11];
 9 struct data{ 
10     string s;
11     int step;
12 }aa;
13 queue<data> que;//队列记录当前情况字符串以及步数 
14 map<string,bool> m;
15 int main(){
16     cin>>start>>end;
17     while(cin>>a[way]>>b[way])
18         way++;
19     way--;//变换种类 
20     aa.s=start;
21     aa.step=0;
22     que.push(aa);
23     m[start]=1;
24     while(!que.empty()){
25         data temp=que.front();
26         que.pop();
27         if(temp.step>10){
28             printf("NO ANSWER!");//超步输出然后直接break 
29             return 0;
30         }
31         if(temp.s==end){
32             printf("%d",temp.step);//如果是最终情况就输出当前步数 
33             return 0;
34         }
35         string t=temp.s;
36         int len=t.length();
37         string next;
38         for(int i=1;i<=way;i++){//将每一种变换方式都尝试并入队 
39             int llen=a[i].length();
40             for(int j=0;j<len;j++){
41                 if(t.substr(j,llen)==a[i]){
42                     next=t;
43                     next.replace(j,llen,b[i]);
44                     if(!m[next]){//看看是否出现过 
45                         m[next]=1;
46                         data tt;
47                         tt.step=temp.step+1;
48                         tt.s=next;
49                         que.push(tt);//如果都能满足就入队 
50                     }
51                 }
52             }
53         }
54     }
55     return 0;
56 }

 

posted @ 2017-03-08 00:52  circlegg  阅读(263)  评论(0编辑  收藏  举报