NOIP 2002 提高组 复赛 字串变换
1.读完题目,样例模拟成功,但感觉该题挺难的,无从下手。
2.搜索网络后,才明白,因为有多种变换规则,故一次变换有多种可能,故采用广度优先遍历方法。
3.数据输入量:至多6个规则 所有字符串长度的上限为 20
4.感觉该题比较简单,编码,提交60分,测试点4,5 均RE。
5.将队列q[1000]改成q[10000],测试点4通过,测试点5还是RE,再改大数组还是无功而返。单向搜索,80分到头。
6.采用双向搜索,参考他人代码,收获很大,但提交还是80分,无奈只好对拍,才发现字符串变换出了问题,必须整个字符串搜索完毕,按规则逐个变换才能算一步变换结束,之前的问题是,字符串只变化第一次找到的字符,没有第二次第三次查找,算法存在较大问题。
7.问题找到后,开始修改,工程量不小。
8.核心代码:p=strstr(b+d+strlen(left[i]),left[i]);//查找剩下的字符串,该题最难之处
9.修改,提交AC。
该题整整编了四天。终于AC了,2017-4-11
附上AC代码,编译环境Dev-C++4.9.9.2
#include <stdio.h>
#include <string.h>
char input[100],output[100];
int lena=0;
struct node{
char in[30];//in[100]
int s;//步数
}q1[1000],q2[1000];//q[1000]
char left[10][30],right[10][30];//变换规则
void bfs(char *input,char *output){
int h1,t1,i,j,d,h2,t2;
char b[30],*p;//b[100]
h1=t1=0;
strcpy(q1[t1].in,input);
q1[t1].s=0;
t1++;
h2=t2=0;
strcpy(q2[t2].in,output);
q2[t2].s=0;
t2++;
if(strcmp(q1[t1-1].in,q2[t2-1].in)==0){
printf("%d\n",q1[t1-1].s+q2[t2-1].s);
return;
}
while(h1<t1&&h2<t2){
if(q1[h1].s+q2[h2].s>10)
break;
strcpy(b,q1[h1].in);
for(i=0;i<lena;i++){//变换处理
p=strstr(b,left[i]);
while(p!=NULL){
d=p-b;
strncpy(q1[t1].in,b,d);
strcat(q1[t1].in,right[i]);
strcat(q1[t1].in,&b[d+strlen(left[i])]);
q1[t1].s=q1[h1].s+1;
for(j=0;j<t2;j++)
if(strcmp(q1[t1].in,q2[j].in)==0){
printf("%d\n",q1[t1].s+q2[j].s);
return;
}
t1++;
p=strstr(b+d+strlen(left[i]),left[i]);//查找剩下的字符串,该题最难之处
}
}
h1++;
strcpy(b,q2[h2].in);
for(i=0;i<lena;i++){//变换处理
p=strstr(b,right[i]);
while(p!=NULL){//原来是if,现改成while
d=p-b;
strncpy(q2[t2].in,b,d);
strcat(q2[t2].in,left[i]);
strcat(q2[t2].in,&b[d+strlen(right[i])]);
q2[t2].s=q2[h2].s+1;
for(j=0;j<t1;j++)
if(strcmp(q2[t2].in,q1[j].in)==0){
printf("%d\n",q1[j].s+q2[t2].s);
return;
}
t2++;
p=strstr(b+d+strlen(right[i]),right[i]);//用了比较长的时间才理解。
}
}
h2++;
}
printf("NO ANSWER!\n");
}
int main(){
int i,j;
char a[30],b[30];
scanf("%s%s",input,output);//读取变换前后字符串
while(scanf("%s%s",a,b)==2){//读取变换规则
strcpy(left[lena],a);
strcpy(right[lena],b);
lena++;
}
bfs(input,output);
return 0;
}