NOIP2004虫食算
Posted 蒟蒻ZJO :-)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2004虫食算相关的知识,希望对你有一定的参考价值。
Description
所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:
43#9865#045
+ 8468#6633
44445509678
其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是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个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解,
Input
输入包含4行。第一行有一个正整数N(N<=26),后面的3行每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有N位。
Output
输出包含一行。在这一行中,应当包含唯一的那组解。解是这样表示的:输出N个数字,分别表示A,B,C……所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。
Sample Input
5
ABCED
BDACE
EBBAA
Sample Output
1 0 3 4 2
Hint
数据规模:
对于30%的数据,保证有N<=10;
对于50%的数据,保证有N<=15;
对于全部的数据,保证有N<=26。
搜索每个字母所表示的数字。 考虑搜索的顺序,因为有进位的影响,先搜在最后一位出现的字母,这样会使后面的可行性剪枝的效果更好。 可行性剪枝 1.从后往前,依次判断。若某一位的三个字母已经搜完,那么就判断一下是否是对的。 2.利用方程思想,x+y=z,知道其中两个之后可以得出第三个的可能的值,然后判断这个值是否已经被用过。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<cctype> 9 #include<cfloat> 10 #include<vector> 11 #include<map> 12 #define RG register 13 using namespace std; 14 char a[100],b[100],c[100],d[100]; 15 int k[100],n,flag=0,has[100],cf[100]; 16 bool CUT() 17 { 18 for (int i=n-1;i>=0;i--) 19 {//a+b==c; 20 int p=k[a[i]-‘A‘],q=k[b[i]-‘A‘],r=k[c[i]-‘A‘]; 21 if (p==-1 || q==-1 || r==-1) continue; 22 if (!((p+q)%n==r || (p+q+1)%n==r)) return true; 23 } 24 for (int i=n-1;i>=0;i--) 25 {//a+?==c; 26 int p=k[a[i]-‘A‘],q=k[b[i]-‘A‘],r=k[c[i]-‘A‘]; 27 if (!(p!=-1 && q==-1 && r!=-1)) continue; 28 int p1=(r-p+n)%n,p2=(r-p-1+n)%n; 29 if (has[p1] && has[p2]) return true; 30 } 31 for (int i=n-1;i>=0;i--) 32 {//?+b==c; 33 int p=k[a[i]-‘A‘],q=k[b[i]-‘A‘],r=k[c[i]-‘A‘]; 34 if (!(p==-1 && q!=-1 && r!=-1)) continue; 35 int p1=(r-q+n)%n,p2=(r-q-1+n)%n; 36 if (has[p1] && has[p2]) return true; 37 } 38 for (int i=n-1;i>=0;i--) 39 {//a+b==?; 40 int p=k[a[i]-‘A‘],q=k[b[i]-‘A‘],r=k[c[i]-‘A‘]; 41 if (!(p!=-1 && q!=-1 && r==-1)) continue; 42 int p1=(p+q)%n; 43 int p2=(p+q+1)%n; 44 if (has[p1] && has[p2]) return true; 45 } 46 return false; 47 } 48 49 bool CUT1() 50 { 51 int u=0; 52 for(int i=n-1;i>=0;i--) 53 { 54 int p=k[a[i]-‘A‘],q=k[b[i]-‘A‘],r=k[c[i]-‘A‘]; 55 if(p==-1 || q==-1 || r==-1) return 0; 56 if(p+q+u>=n) { 57 if((p+q+u-n)!=r) return 1; 58 u=1; 59 } 60 else { 61 if((p+q+u)!=r) return 1; 62 u=0; 63 } 64 } 65 return 0; 66 } 67 void search(int x) 68 { 69 int u=d[x]-‘A‘; 70 if(flag) return; 71 if(CUT1()) return; 72 if(CUT()) return; 73 if(x==n){ 74 for(int i=0;i<n;i++) 75 printf("%d ",k[i]); 76 flag=1; 77 return; 78 } 79 for(int i=n-1;i>=0;i--) 80 { 81 if(has[i]) continue; 82 k[u]=i; 83 has[i]=1; 84 search(x+1); 85 k[u]=-1; 86 has[i]=0; 87 } 88 } 89 int main() 90 { 91 freopen("!.in","r",stdin); 92 freopen("!.out","w",stdout); 93 scanf("%d",&n);scanf("%s",a);scanf("%s",b);scanf("%s",c); 94 memset(k,-1,sizeof(k)); 95 for(int i=n-1,j=0;i>=0;i--) 96 { 97 char u1=a[i],u2=b[i],u3=c[i]; 98 if(!cf[u1-‘A‘]) d[j]=u1,j++,cf[u1-‘A‘]=1; 99 if(!cf[u2-‘A‘]) d[j]=u2,j++,cf[u2-‘A‘]=1; 100 if(!cf[u3-‘A‘]) d[j]=u3,j++,cf[u3-‘A‘]=1; 101 } 102 search(0); 103 return 0; 104 }
以上是关于NOIP2004虫食算的主要内容,如果未能解决你的问题,请参考以下文章