洛谷OJ P1032 字串变换 解题报告

洛谷OJ P1032 字串变换 解题报告

by MedalPluS

  【题目描述】

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

  【分析】

  一开始拿到题目感觉有的懵懵哒,然后就明白了,这里翻译一下火星文:

  给你两个字符串s1,s2,再给你许多许多变换方式使得s1=s2,求最少步数,大于10就输出NO ANSWER

  我想,这不就是搜索求最优值问题么?然后就自然地想到了迭代加深(这里不赘述)

  也就是最多层次为10,结果还是莫名其妙的TLE了。。。

  然后算了一下,对于变换方式,可能有许多许多,这也就意味着解空间树不是一个二叉树,k叉树!也就是nk的复杂度,很明显TLE么。。

  为什么要用迭代加深呢?怕空间不够!来算一下空间,20*20*19/2<107所以也就是虚惊一场,其实空间足够大

  但是普通的BFS绝对会TLE的,这题有个特点,那就是知道起始点和终止点

  然后我们采用双向BFS,加快速度

  然后就AC了

  【代码】

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <string>
  4 #include <map>
  5 #include <cstdlib>
  6 #include <queue>
  7 using namespace std;
  8 
  9 const int maxn=1001;
 10 
 11 struct node{
 12     int dfn;
 13     string data;
 14 };
 15 
 16 int l;
 17 string c[maxn],c_[maxn];//c=>c_
 18 string s1,s2;
 19 map<string,int> hash_f,hash_b;
 20 queue<node> f,b;
 21 
 22 string Getstr(string s,int l,int r){
 23     string base;
 24     while(l<=r)
 25         base+=s[l++];
 26     return base;
 27 }
 28 
 29 void expand_f(){
 30     node head=f.front();
 31     string tmp,cc,res;
 32     f.pop();
 33     if(head.dfn+1>10)return;
 34     int i,j,k,kk;
 35     for(i=0;i<head.data.size();i++)
 36       for(j=i;j<head.data.size();j++)
 37       {
 38           tmp=Getstr(head.data,i,j);
 39           cc="";
 40           for(k=0;k<i;k++)cc+=head.data[k];
 41           res=cc;
 42         for(k=1;k<=l;k++)
 43             if(tmp==c[k])
 44             {
 45                 res+=c_[k];
 46                 for(kk=j+1;kk<head.data.size();kk++)
 47                   res+=head.data[kk];
 48                 if(hash_b[res]){printf("%d",hash_b[res]+head.dfn+1);exit(0);}
 49                 if(hash_f[res])continue;
 50                 else hash_f[res]=head.dfn+1;
 51                 f.push((struct node){head.dfn+1,res});
 52               res=cc;
 53             }
 54       }
 55 }
 56 
 57 void expand_b(){
 58     node head=b.front();
 59     string tmp,cc,res;
 60     b.pop();
 61     if(head.dfn+1>10)return;
 62     int i,j,k,kk;
 63     for(i=0;i<head.data.size();i++)
 64       for(j=i;j<head.data.size();j++)
 65       {
 66           tmp=Getstr(head.data,i,j);
 67           cc="";
 68           for(k=0;k<i;k++)cc+=head.data[k];
 69           res=cc;
 70         for(k=1;k<=l;k++)
 71             if(tmp==c_[k])
 72             {
 73                 res+=c[k];
 74                 for(kk=j+1;kk<head.data.size();kk++)
 75                   res+=head.data[kk];
 76                 if(hash_f[res]){printf("%d",hash_f[res]+head.dfn+1);exit(0);}
 77             if(hash_b[res])continue;
 78                 else hash_b[res]=head.dfn+1;
 79                 b.push((struct node){head.dfn+1,res});
 80                 res=cc;//clear
 81             }
 82       }
 83 }
 84 
 85 void bfs(){
 86     int ex,len1,len2;
 87     hash_f[s1]=0;
 88     hash_b[s2]=0;
 89     f.push((struct node){0,s1});
 90     b.push((struct node){0,s2});
 91     while(1){
 92         len1=f.size();
 93         len2=b.size();
 94         if(len1==len2 && !len2)break;
 95         //按秩拓展
 96         if(len1>len2){
 97             expand_f();
 98             if(len2)expand_b();
 99         }
100         else {
101             expand_b();
102             if(len1)expand_f();
103         }
104     }
105 }
106 
107 int main(){
108     cin>>s1>>s2;
109     l=1;
110     while(cin>>c[l]){
111         cin>>c_[l];
112         l++;
113     }
114     l--;
115     bfs();
116     printf("NO ANSWER!");
117     return 0;
118 }

 

posted @ 2015-05-10 00:02  MedalPluS  阅读(615)  评论(0编辑  收藏  举报