【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 }

时间: 2024-10-25 07:19:13

【NOIP2004】虫食算的相关文章

69. [NOIP2004] 虫食算

69. [NOIP2004] 虫食算 ★★★   输入文件:alpha.in   输出文件:alpha.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045    + 8468#6633 ----------- 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是

NOIP2004 虫食算

四.虫食算 (alpha.pas/dpr/c/cpp) [问题描述] 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045     +    8468#6633        44445506978 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许

[NOIP2004]虫食算 T4 简单搜索+剪枝

最近在刷搜索套餐 我先做了一道简单的 虫食算.... 我GO die了........... 这都是啥啊!!!!!!!!!!!!!!! 总之就是一个搜啊.... 从最右面开始搜 每一行行尾进行check 基本上能过9个点........ 剪枝的话 ,考虑检索前面的每一行 如果改行的数字都己经试过,那么就可以判断合法性,如果已经有两个试过的话,考虑第三个数是否可能(可能已经被用过) 注意:试数的时候从后向前试...坑爹的数据 注意进位即可 下面是代码,调试信息懒得删....搜索的第四层可删 略长.

(DFS)noip2004——虫食算

1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 char a[4][28]; 5 bool vix[100],vi[28]; 6 int c[100],ge=1,an[100],t; 7 bool judge1() 8 { 9 char x,y,z; 10 for(int i=t;i>0;i--) 11 { 12 x=a[1][i];y=a[2][i];z=a[3][i]; 13 if

[Noip2004]虫食算 dfs

搜索问题的关键:优秀的搜索策略以及行之有效的减枝 对于这道题我们阶乘搜肯定不行所以我们按位搜,我们对每一位的三个数进行赋值,然后判解. 对于此一类的搜索乘上一个几十的常数来减枝往往要比直接搜要快得多,因为这样的问题他们都会有一个庞大的"之后",而且判断不存在较为容易,以我们多花一些时间进行减枝往往能达到剪掉许多枝的效果. 搜索还是看感觉,倒搜还是比正搜快...... #pragma GCC optimize("O3") #include <cstdio>

[NOIP2004] 提高组 洛谷P1092 虫食算

题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用

洛谷—— P1092 虫食算

https://www.luogu.org/problem/show?pid=1092 题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: http://paste.ubuntu.com/25448822/ 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前

虫食算

题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用

洛谷 P1092 虫食算 Label:dfs

题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用