洛谷 P1032 [NOIP2002 T2] 字串变换

来源:互联网 发布:java 圆周率 编辑:程序博客网 时间:2024/06/02 03:14

题目描述

已知有两个字串 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 xyzabc xuud yy yz
输出样例#1:
3










~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

bfs+字符串~

刷新世界观的神题……

(1)队列要建成string型的;

(2)map还可以当做记录状态的数组来用;

(3)队列还有find,replace等等神奇的操作;

(4)不定项输入用scanf可能会RE,cin实在强大;

(5)这题是没法在本机调试的,只能在OJ上交后再改错,帮我迅速拉低正确率……

这道题用到了类似bfs的算法。

把目标串和初始串分别加入队列中,每次双向更新并记录可以更新到的字符串以及其改变次数,直到某一队列中更新出另一队列曾更新出的结果,就直接输出,因为此时的解一定是最优的。

(输出结果要-2,因为刚开始为了区分是否更新过,初始两串都记为度1。)


#include<cstdio>#include<cstring>#include<iostream>#include<queue>#include<map>using namespace std;int n,len;queue<string> qa,qb;string a,b,s1[21],s2[21];map<string,int> ba,bb;int main(){cin>>a>>b;n=1;while(cin>>s1[n]>>s2[n]) n++;n--;ba[a]=1;bb[b]=1;qa.push(a);qb.push(b);while(1){if(qa.empty() || qb.empty()){printf("NO ANSWER!\n");return 0;}string nowa=qa.front(),nowb=qb.front();for(int i=1;i<=n;i++){int kkz=0;while((kkz=nowa.find(s1[i],kkz))!=-1){len=s1[i].size();nowa.replace(kkz,len,s2[i]);if(!ba[nowa]){ba[nowa]=ba[qa.front()]+1;qa.push(nowa);}if(bb[nowa]){printf("%d\n",ba[nowa]+bb[nowa]-2);return 0;}kkz++;nowa=qa.front();}kkz=0;while((kkz=nowb.find(s2[i],kkz))!=-1){len=s2[i].size();nowb.replace(kkz,len,s1[i]);if(!bb[nowb]){bb[nowb]=bb[qb.front()]+1;qb.push(nowb);}if(ba[nowb]){printf("%d\n",bb[nowb]+ba[nowb]-2);return 0;}kkz++;nowb=qb.front();}}qa.pop();qb.pop();}}



1 0
原创粉丝点击