NOIP2009 提高组 复赛 spy 潜伏者
1.很快读懂题意,想用C++里的map但忍住了。采用数学中的映射关系,'A'-0,'B'-1,'C'-2依次类推。
2.开一个密码明码对应数组,a[i]=k,i是密码,对应字母i+'A',k是明码,对应字母k+'A'。
3.初始化时,将a数组中的数值初始化为-1,因为'A'-0。
4.再次遇到a[j]时,若a[j]!=k,表明一个密码对应两个字母。
5.若count==26,表明26个字母都统计到了。
6.写代码时,小错误不断,如for循环忘记写花括号,忘记了j=s3[i]-'A',查了个半天。
7.三个样例通过后,提交90分,很是满意,考试时,应该不会为了没拿到的10分停留了,继续下一道。
耗时:30分钟。
8.搜索网络,发现http://wenku.baidu.com/link?url=mc1Mdx_N2Dy2Gld11CzsG23lmwL7FuBzKMvy39LsS7Kls6Up123QpldGbKV8X1MeQRIOLy6ARJmjtGYOfbKDICaZ2RUZ5gcfkiQhcOdfF3e与本人问题一致:(本人考试的时候想不到啊)
需要注意不僅要判斷是否每一個密文字母都存在惟一對應的明文字母,還要判斷是否每一個明文字母都存在惟一對應的密文字母。(去年我沒判斷這個,
所以測試點三WA了,九十分)
9.马上进行修改:再开了一个明码的数组b[26]。
难度:90分,简单
难度:100分,难
附上AC代码,编译环境Dev-C++4.9.9.2
//2009 syp
#include <stdio.h>
#include <string.h>
int main(){
char s1[100+10],s2[100+10],s3[100+10];
int a[26];//26个字母
int b[26];
int len1,len3;
int i,j,k;//字母到数字的映射
int count=0;
scanf("%s%s%s",s1,s2,s3);
memset(a,-1,sizeof(a));
memset(b,-1,sizeof(b));
len1=strlen(s1);
len3=strlen(s3);
for(i=0;i<len1;i++){
j=s1[i]-'A';
k=s2[i]-'A';
if(a[j]==-1&&b[k]==-1){
a[j]=k;
b[k]=j;
count++;//统计字母
}else if(a[j]!=k||b[k]!=j)//已赋值
break;
}
if(i==len1){//s1中每个字母都遍历了
if(count==26){
for(i=0;i<len3;i++){
j=s3[i]-'A';
printf("%c",a[j]+'A');
}
printf("\n");
}else//没到26个字母
printf("Failed\n");
}else{
printf("Failed\n");
}
return 0;
}
附上90分代码,编译环境Dev-C++4.9.9.2
//2009 syp
#include <stdio.h>
#include <string.h>
int main(){
char s1[100+10],s2[100+10],s3[100+10];
int a[26];//26个字母
int len1,len3;
int i,j,k;//字母到数字的映射
int count=0;
scanf("%s%s%s",s1,s2,s3);
memset(a,-1,sizeof(a));
len1=strlen(s1);
len3=strlen(s3);
for(i=0;i<len1;i++){
j=s1[i]-'A';
k=s2[i]-'A';
if(a[j]==-1){
a[j]=k;
count++;//统计字母
}else if(a[j]!=k)//已赋值
break;
}
if(i==len1){//s1中每个字母都遍历了
if(count==26){
for(i=0;i<len3;i++){
j=s3[i]-'A';
printf("%c",a[j]+'A');
}
printf("\n");
}else//没到26个字母
printf("Failed\n");
}else{
printf("Failed\n");
}
return 0;
}