65. [NOIP2002] 字串变换
时间限制:1 s 内存限制:128 MB- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<map>
- #include<string>
- #include<queue>
- using namespace std;
- struct node
- {
- string s;int num;
- };
- queue<node>q1,q2;
- map<string,int>m1,m2;
- string changings[6][2];
- int cnt,ans;
- string become(string now,int pos,int n,string tmp)
- {
- return now.replace(pos,n,tmp);
- }
- bool dbfs()
- {
- while(!q1.empty()&&!q2.empty())
- {
- node s1=q1.front(),s2;q1.pop();
- int len=s1.s.size();
- for(int i=0;i<len;i++)
- for(int j=0;j<cnt;j++)
- {
- int siz=changings[j][0].size();
- if(i+siz-1<len&&!s1.s.compare(i,siz,changings[j][0])&&!m1.count(become(s1.s,i,siz,changings[j][1])))
- {
- s2.s=become(s1.s,i,siz,changings[j][1]);
- s2.num=s1.num+1;
- if(s2.num>10)return 0;
- m1[s2.s]=s2.num;q1.push(s2);
- if(m2.count(s2.s))
- {
- ans=s2.num+m2[s2.s];
- return 1;
- }
- }
- }
- s1=q2.front(),s2;q2.pop();
- len=s1.s.size();
- for(int i=0;i<len;i++)
- for(int j=0;j<cnt;j++)
- {
- int siz=changings[j][1].size();
- if(i+siz-1<len&&!s1.s.compare(i,siz,changings[j][1])&&!m2.count(become(s1.s,i,siz,changings[j][0])))
- {
- s2.s=become(s1.s,i,siz,changings[j][0]);
- s2.num=s1.num+1;
- if(s2.num>10)return 0;
- m2[s2.s]=s2.num;q2.push(s2);
- if(m1.count(s2.s))
- {
- ans=s2.num+m1[s2.s];
- return 1;
- }
- }
- }
- }
- return 0;
- }
- int haha()
- {
- freopen("string.in","r",stdin);
- freopen("string.out","w",stdout);
- node a,b;cin>>a.s>>b.s;
- if(a.s==b.s)
- {
- cout<<0;
- return 0;
- }
- a.num=b.num=0;
- q1.push(a);q2.push(b);
- while(cin>>changings[cnt][0]>>changings[cnt][1])cnt++;
- m1[a.s]=0;m2[b.s]=0;
- if(dbfs())cout<<ans;
- else puts("NO ANSWER!");
- }
- int sb=haha();
- int main(){;}
[问题描述]
已知有两个字串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
正解就是搜,深搜会超时,可以考虑广搜,即双向广搜,可以防止被卡数据,比如正向搜过慢,而反向搜很快的点。
先贴一发我dfs+神剪枝+卡数据的搜
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<map> using namespace std; string A,B,a[10],b[10]; int n=1,ans=11,cnt=0; map<string,int> mp; void dfs(string x,int len) { cnt++; if(cnt>=40000){printf("NO ANSWER! ");exit(0);}//深搜次数过多直接输出无解,卡数据。 if(len>10||x.size()>20||len>ans)return; if(x==B){ ans=min(ans,len); return; } string f=x;int k; for(int i=1;i<=n;i++){ for(int j=0;j<x.size();j++) { k=x.find(a[i],j); if(k<100&&k>=0) { int l=a[i].size(); x.replace(k,l,b[i]); if(!mp.count(x))mp[x]=len,dfs(x,len+1); else if(len<mp[x])dfs(x,len+1); x=f; } } } } int yjn() { freopen("string.in","r",stdin); freopen("string.out","w",stdout); cin>>A>>B; while(cin>>a[n])cin>>b[n++]; n--; mp[A]=++cnt; dfs(A,0); if(ans==11)printf("NO ANSWER! "); else cout<<ans; } int qty=yjn(); int main(){;}
再贴一发正解