codevs 1064 虫食算
2004年NOIP全国联赛提高组
所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:
43#9865#045
+ 8468#6633
44445506978
其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5。
现在,我们对问题做两个限制:
首先,我们只考虑加法的虫食算。这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0。
其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用相同的字母表示,不同的数字用不同的字母表示。如果这个算式是N进制的,我们就取英文字母表午的前N个大写字母来表示这个算式中的0到N-1这N个不同的数字:但是这N个字母并不一定顺序地代表0到N-1)。输入数据保证N个字母分别至少出现一次。
BADC
+ CBDA
DCCC
上面的算式是一个4进制的算式。很显然,我们只要让ABCD分别代表0123,便可以让这个式子成立了。你的任务是,对于给定的N进制加法算式,求出N个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解,
输入包含4行。第一行有一个正整数N(N<=26),后面的3行每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有N位。
输出包含一行。在这一行中,应当包含唯一的那组解。解是这样表示的:输出N个数字,分别表示A,B,C……所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。
5
ABCED
BDACE
EBBAA
1 0 3 4 2
对于30%的数据,保证有N<=10;
对于50%的数据,保证有N<=15;
对于全部的数据,保证有N<=26。
1 /*这个题目需要注意的细节很多,尤其是jw[k]==0的回溯一定不能忘记*/ 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 int atos['Z'+1]; 8 char jz[4][30]; 9 bool flag[30]={0}; 10 int n; 11 int jw[30]={0}; 12 void dfs(int k,int p) 13 { 14 for(int i=1;i<=n;++i) 15 { 16 if(atos[jz[1][i]]>=0&&atos[jz[2][i]]>=0&&atos[jz[3][i]]>=0) 17 { 18 int p=atos[jz[1][i]]+atos[jz[2][i]]; 19 if(p%n!=atos[jz[3][i]]&&(p+1)%n!=atos[jz[3][i]]) 20 return; 21 } 22 } 23 if(k<=0) 24 { 25 printf("%d",atos['A']); 26 for(int i='B';i<='A'+n-1;++i) 27 printf(" %d",atos[i]); 28 printf(" "); 29 exit(0); 30 } 31 if(p==3) 32 { 33 int temp=atos[jz[1][k]]+atos[jz[2][k]]+jw[k+1]; 34 if(atos[jz[3][k]]>=0) 35 { 36 if(atos[jz[3][k]]==temp) 37 { 38 dfs(k-1,1); 39 } 40 else if(atos[jz[3][k]]+n==temp) 41 { 42 jw[k]=1; 43 dfs(k-1,1); 44 jw[k]=0; 45 }else return; 46 } 47 else 48 { 49 if(temp>=n) 50 { 51 jw[k]=1; 52 temp-=n; 53 } 54 if(!flag[temp]) 55 { 56 flag[temp]=true; 57 atos[jz[3][k]]=temp; 58 dfs(k-1,1); 59 flag[temp]=false; 60 atos[jz[3][k]]=-1; 61 } 62 jw[k]=0;/*前面一开始写了一个if(flag[temp]) return 结果jw没被重置,倒数第二组数据,就错了*/ 63 } 64 65 }else if(p==2) 66 { 67 if(atos[jz[2][k]]>=0) 68 { 69 dfs(k,3); 70 } 71 else { 72 for(int j=0;j<=n-1;++j) 73 { 74 if(!flag[j]) 75 { 76 flag[j]=true; 77 atos[jz[2][k]]=j; 78 dfs(k,3); 79 flag[j]=false; 80 atos[jz[2][k]]=-1; 81 } 82 } 83 } 84 } 85 else if(p==1) 86 { 87 if(atos[jz[1][k]]>=0) 88 { 89 dfs(k,2); 90 } 91 else { 92 for(int j=0;j<=n-1;++j) 93 { 94 if(!flag[j]) 95 { 96 flag[j]=true; 97 atos[jz[1][k]]=j; 98 dfs(k,2); 99 flag[j]=false; 100 atos[jz[1][k]]=-1; 101 } 102 } 103 } 104 } 105 } 106 int main() 107 { 108 scanf("%d",&n); 109 for(int i=1;i<=3;++i) 110 scanf("%s",jz[i]+1); 111 memset(atos,-1,sizeof(atos)); 112 dfs(n,1); 113 return 0; 114 }