[NOIP2004] 提高组 洛谷P1092 虫食算
Posted SilverNebula
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOIP2004] 提高组 洛谷P1092 虫食算相关的知识,希望对你有一定的参考价值。
题目描述
所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:
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个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解
输入输出格式
输入格式:
包含四行。第一行有一个正整数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。
noip2004提高组第4题
强大的搜索。
基本思想就是枚举每个字母代表的值,并且带入计算。
把每一列当做一个整体处理,从低位往高位扫(方便计算进位)。
有一个很强的剪枝:当发现高位的某一列三个数都填上以后,如果两个加数不管进不进位都不能得到填上去的和,说明方案肯定不可行,直接剪枝。具体看代码。
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 char s[30]; 9 int n; 10 int a[30],b[30],c[30]; 11 int w[30];//字母对应数字 12 bool vis[30]; 13 bool DFS(int p,int tmp){ 14 if(!p){ 15 if(tmp)return 0; 16 return 1; 17 } 18 int i,j,k; 19 for(k=p;k;--k){ 20 if(w[a[k]]!=-1 && w[b[k]]!=-1 && w[c[k]]!=-1 && 21 ( (w[a[k]]+w[b[k]])%n!=w[c[k]] && (w[a[k]]+w[b[k]]+1)%n!=w[c[k]] ) ) return 0; 22 } 23 if(w[a[p]]!=-1 && w[b[p]]!=-1){ 24 int tp1=w[a[p]]+w[b[p]]+tmp; 25 if(w[c[p]]!=-1){ 26 if(tp1%n!=w[c[p]])return 0; 27 else return DFS(p-1,tp1/n); 28 } 29 else{ 30 int tg=tp1%n;if(vis[tg])return 0; 31 w[c[p]]=tg; vis[tg]=1; 32 if(DFS(p-1,tp1/n))return 1; 33 w[c[p]]=-1; vis[tg]=0; 34 return 0; 35 } 36 } 37 for(register int i=n-1;i>=0;--i){//a 38 if(vis[i] && w[a[p]]!=i)continue; 39 if(w[a[p]]!=-1 && i!=w[a[p]])continue; 40 for(register int j=n-1;j>=0;--j){//b 41 if(vis[j] && w[b[p]]!=j)continue; 42 if(w[b[p]]!=-1 && j!=w[b[p]])continue; 43 k=(i+j+tmp)%n;//c 44 if(w[c[p]]!=-1 && k!=w[c[p]])continue; 45 if(vis[k] && w[c[p]]!=k)continue; 46 int tp1=i+j+tmp; 47 int cp1=w[a[p]]; 48 int cp2=w[b[p]]; 49 int cp3=w[c[p]]; 50 bool vp1=vis[i]; 51 bool vp2=vis[j]; 52 bool vp3=vis[k]; 53 w[a[p]]=i;vis[i]=1; 54 w[b[p]]=j;vis[j]=1; 55 w[c[p]]=k;vis[k]=1; 56 if(DFS(p-1,tp1/n))return 1; 57 w[a[p]]=cp1;vis[i]=vp1; 58 w[b[p]]=cp2;vis[j]=vp2; 59 w[c[p]]=cp3;vis[k]=vp3; 60 } 61 62 } 63 return 0; 64 } 65 int main(){ 66 memset(w,-1,sizeof w); 67 scanf("%d",&n); 68 int i,j; 69 scanf("%s",s+1); 70 for(i=1;i<=n;i++)a[i]=s[i]-‘A‘+1; 71 scanf("%s",s+1); 72 for(i=1;i<=n;i++)b[i]=s[i]-‘A‘+1; 73 scanf("%s",s+1); 74 for(i=1;i<=n;i++)c[i]=s[i]-‘A‘+1; 75 DFS(n,0); 76 for(i=1;i<=n;i++)printf("%d ",w[i]); 77 return 0; 78 }
以上是关于[NOIP2004] 提高组 洛谷P1092 虫食算的主要内容,如果未能解决你的问题,请参考以下文章