Evanyou Blog 彩带

P1032 字串变换

题目描述

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

 

posted @ 2018-03-13 15:50  five20  阅读(502)  评论(0编辑  收藏  举报
Live2D