NOIP 2000 提高组 复赛 单词接龙
1.程序编写过程中,发现接龙处的判断编写有误,马上着手修改。
2.样例通过,提交40分,错了测试点1-4.
3.下载测试点1一看,傻眼了,原来有这样的测试数据:
输入:
1
envelope
e
输出:
15
4.上述测试点是挺经典的,不容易考虑到。envelope envelope 拼接成envelopenvelope
5.归根结底,还是接龙处的编写出现严重失误。
6.修改,提交,还错测试点2-4.
7.下载测试点2数据一看,更是奇葩:
输入:
2
abababab
abababc
a
输出:
19
经理解后,输出结果应如下解释:
abababab
abababab
abababc
8.应采用最小交叠,这样输出长度才最大,还是修改判断接龙处函数。
9.修改提交,错了测试点4,真是感慨,该题要考虑的情况真多啊,难不在深度优先遍历,难在接龙处判定。
10.测试点4数据也挺奇葩,接了半天龙,单词长度还不如单个的单词长。
输入:
8
no
new
name
never
national
necessary
ever
me
n
输出:
9
10.修改,提交AC。
11.该题奇难无比,不是难在深度优先遍历,而是难在接龙处的判断函数编写,真是服了,原来可以这样难。
附上AC代码,编译环境Dev-C++4.9.9.2
#include <stdio.h>
#include <string.h>
int n;
char input[60][100];
char head[10];
int vis[60];
char dragon[3000];
char cur[100];
int max=0;
int cmp(char *first,char *second){
int len1,len2,i,j,k,len;
len1=strlen(first);
len2=strlen(second);
len=len1>len2?len2:len1;
if(strcmp(first,second)==0){
i=len1-1;
j=0;
while(i<len1&&j<len2&&first[i]==second[j]){
i++;//此处写成i--查了会
j++;
}
if(j==len-1)
return 0;
}
for(k=1;k<len;k++){//k=len-1的目的是避免 邻的两部分存在包含关系;仔细一想,这个思路不行,还是要从k=len判断,因其可能完全重合,无论怎么移,都重合。
i=len1-k;
j=0;
while(i<len1&&j<len2&&first[i]==second[j]){
i++;//此处写成i--查了会
j++;
}
if(j==k)
break;
}
if(k==len)
return 0;
if(j==k)
return j;
}
void dfs(int step){
int len,i,k,j,len2;
char t[100];
for(i=1;i<=2*n;i++)
if(vis[i]==0){
k=cmp(cur,input[i]);
if(k>0){
vis[i]=1;
len=strlen(dragon);
len2=strlen(input[i]);
for(j=k;j<len2;j++)//字符串拼接
dragon[len+j-k]=input[i][j];
dragon[len+len2-k]='\0';
len2=strlen(dragon);
if(max<len2)
max=len2;
strcpy(t,cur);
strcpy(cur,input[i]);
dfs(step+1);
strcpy(cur,t);
dragon[len]='\0';
vis[i]=0;
}
}
}
int main(){
int i,j,len;
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%s",input[i]);
strcpy(input[n+i],input[i]);
}
scanf("%s",head);
for(i=1;i<=2*n;i++){
if(input[i][0]==head[0]){
strcpy(dragon,input[i]);
vis[i]=1;
len=strlen(dragon);
if(max<len)
max=strlen(dragon);//要过测试点4,此处必须对max赋值
strcpy(cur,input[i]);
dfs(1);
vis[i]=0;
}
}
printf("%d\n",max);
return 0;
}
2017-3-31 22:05