1016 [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 B1A_1\ B_1A1 B1 \
A2 B2A_2\ B_2A2 B2 |-> 变换规则
... ... /
所有字符串长度的上限为 20。
 

输出描述:

输出格式如下:
若在10步(包含 10步)以内能将A变换为B,则输出最少的变换步数;否则输出"NO ANSWER!"

示例1

输入
abcd xyz
abc xu
ud y
y yz
输出
3
 

解答

1.读完题目,样例模拟成功,但感觉该题挺难的,无从下手。
2.看了雨巨的写法,才知道可以bfs,因为条件很少,所以直接pos = string.find(a[i]);tmp.erase(pos,a[i].size());tmp.insert(pos,b[i]);就可以实现字串查找和替换
3.然后想到同一个字串有多个位置可以替换 就可以改pos = string.find(a[i],j) 用j来循环原串中的位置
4.然后就是各种剪枝,最后发现还是不行,只能双向广搜。
5.最后看了别人的代码,改了很多细节。。。交上去始终a不了,才发现搜的时候忘记传ed了。。。。好菜
6.过程中发现别人代码有几个bug,比如应该是<cnt 还有q.push(mp[tmp]) 才对;
7.


//-------------------------代码----------------------------

//#define int LL
const int N = 1e6+10;
string st,ed;
map<string,int>mp;
string vis[N];
int cnt = 1;
string a[N],b[N];
int distA[N],distB[N];
int n = 0;
int bfs(string st,int dist[],string a[],string b[]) {
    queue<int> q;
    mp[st]= n;
    vis[n]=st;
    q.push(n);
    dist[n]=0;
    n ++ ;
    while(q.size()) {
        int t=q.front();q.pop();
    //  cout<<ys[x]<<endl;
        if(dist[t] == 5)
            return 0;
        string cur=vis[t];
        int l=cur.length();
        for(int i = 1;i <= cnt;i++)
        {
            for(int j = 0;j < l;)
            {
                string tmp=cur;
                int pos=tmp.find(a[i],j);
                if(pos == string::npos)break;
                j = pos+1;
                tmp.erase(pos,a[i].length());
                tmp.insert(pos,b[i]);
                if(mp.find(tmp)==mp.end())
                {
                    mp[tmp]=n;
                    vis[n]=tmp;
                    dist[n]=dist[t]+1;
                    q.push(n);n ++ ;
                }
                else if(dist[mp[tmp]]==-1)
                {
                    dist[mp[tmp]]=dist[t]+1;
                    q.push(n);
                }           
            }
        }
    }
    return 0;
}

void solve()
{
     cin>>st>>ed;
//     V<V<int>>mp(n+1,V<int>(m+1));    
    memset(distA,-1,sizeof distA);
    memset(distB,-1,sizeof distB);
    cnt = 1;
    while(cin>>a[cnt]>>b[cnt]) { cnt ++ ;}

    int m1 = bfs(st,distA,a,b);
    int m2 = bfs(ed,distB,b,a);
    int ans = 1000;
    for(int i = 0;i<=n;i++) {
        if(distA[i] != -1 && distB[i] != -1) {
            ans = min(ans,distA[i] + distB[i]);
        }
    }
    
    
    if(ans > 10) cout<<"NO ANSWER!"<<endl;
    else cout<<ans;
}

signed main(){
    clapping();TLE;
    
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

posted @ 2022-07-01 14:04  er007  阅读(29)  评论(0编辑  收藏  举报