虫食算(搜索)

匿名 (未验证) 提交于 2019-12-03 00:20:01

题目:

虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:

      43#9865#045      +   8468#6633      =   44445506678

  其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5。
  现在,我们对问题做两个限制:
  首先,我们只考虑加法的虫食算。这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0。
  其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用相同的字母表示,不同的数字用不同的字母表示。如果这个算式是N进制的,我们就取英文字母表午的前N个大写字母来表示这个算式中的0到N-1这N个不同的数字:但是这N个字母并不一定顺序地代表0到N-1)。输入数据保证N个字母分别至少出现一次。

       BADC          + CRDA          = DCCC

  上面的算式是一个4进制的算式。很显然,我们只要让ABCD分别代表0123,便可以让这个式子成立了。你的任务是,对于给定的N进制加法算式,求出N个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解。

如:

5ABCED BDACE EBBAA

ABCDE都是相同的数,ABCED+BDACE=EBBAA,求它的A,B,C,D,E的数值。

思路:可不可以一步一步枚举,A=1到10,B=1到10......是可以但是(忘给了一个条件n<27)

。。。。。。无语恶心吧

我们也可以dfs一下,一步一步进行除,但是(n<27


。。。。。。

我们也可以对dfs进行优化,两步两步除,但是(n<27)


。。。。。。

只能三步三步除了。。。。。。

先是读入(建议用二维数组,方便一点)

void read() {     scanf("%d",&n);     for (int i=0; i<3; i++){//总共有三行数。。。         while (ch<'A' || ch>'Z') ch=getchar();         for (int j=1; j<=n; j++) a[i][j]=ch-'A',ch=getchar();     } }

接下来我来解释一下我的个个变量的意义:

int f[30];//他算出来的数值 int a[3][30];//读入的ABCDE...... int g[30];//判断其是否计算过 int jw[30];//计算储存数值 int n;//读入的个数 bool ok=0;//判断是否输出 char ch;//用在快读中

这样就可以进行递推啦!(dfs(0,n))

if (x<2){//当x=0,或x=1时         int k=1-x;         if (!f[a[x][y]]){//判断是否用过             if (f[a[k][y]] && f[a[2][y]]){//如果俩都用过                 if (!g[(f[a[2][y]]-f[a[k][y]]-jw[y+1]+n)%n]){//判断是否计算过 		    f[a[x][y]]=(f[a[2][y]]-f[a[k][y]]-jw[y+1]+n)%n+1;                     g[f[a[x][y]]-1]=1;                     dfs(x+1,y);//递推下一位                     if (ok) return;//如果已经输出了,跳出dfs                     g[f[a[x][y]]-1]=0;//回溯一步                     f[a[x][y]]=0;//同上                 }                 return;//跳出循环             }             for (int i=n-1; i>=0; i--) if (!g[i]){//判断                 f[a[x][y]]=i+1;                 g[f[a[x][y]]-1]=1;                 dfs(x+1,y);                 g[f[a[x][y]]-1]=0;                 f[a[x][y]]=0;             }             return;         }         dfs(x+1,y);//dfs一下         return;     }

 if (x==2){//和上面的差不多,稍作修改         if (!f[a[x][y]]){             f[a[x][y]]=(f[a[0][y]]-1+f[a[1][y]]-1+jw[y+1])%n+1;             if (!g[f[a[x][y]]-1]){                 g[f[a[x][y]]-1]=1;                 jw[y]=(jw[y+1]+f[a[0][y]]-1+f[a[1][y]]-1)/n;                 dfs(0,y-1);                 g[f[a[x][y]]-1]=0;             }             f[a[x][y]]=0;             return;         }         if ((f[a[0][y]]-1+f[a[1][y]]-1+jw[y+1])%n==f[a[2][y]]-1){//判断             jw[y]=(jw[y+1]+f[a[0][y]]-1+f[a[1][y]]-1)/n;             dfs(0,y-1);         }         return;     }

下面是输出

if (y==0){//如果算完了         if (f[a[0][1]]-1+f[a[1][1]]-1+jw[2]==f[a[2][1]]-1){//如果满足条件             for (int i=0; i<n-1; i++) printf("%d ",f[i]-1);             printf("%d",f[n-1]-1);             ok=1;//让下面一直跳出循环         }         return;//return掉     }

这样基本上就完事了

下面是代码(不是伪的)

#include<bits/stdc++.h> int f[30]; int a[3][30]; int g[30]; int jw[30]; int n; int ok; char ch; void dfs(int x,int y){     if (ok) return;     if (y==0){         if (f[a[0][1]]-1+f[a[1][1]]-1+jw[2]==f[a[2][1]]-1){             for (int i=0; i<n-1; i++) printf("%d ",f[i]-1);             printf("%d",f[n-1]-1);             ok=1;         }         return;     }     if (x<2){         int k=1-x;         if (!f[a[x][y]]){             if (f[a[k][y]] && f[a[2][y]]){                 if (!g[(f[a[2][y]]-f[a[k][y]]-jw[y+1]+n)%n]){ 					f[a[x][y]]=(f[a[2][y]]-f[a[k][y]]-jw[y+1]+n)%n+1;                     g[f[a[x][y]]-1]=1;                     dfs(x+1,y);                     if (ok) return;                     g[f[a[x][y]]-1]=0;                     f[a[x][y]]=0;                 }                 return;             }             for (int i=n-1; i>=0; i--) if (!g[i]){                 f[a[x][y]]=i+1;                 g[f[a[x][y]]-1]=1;                 dfs(x+1,y);                 g[f[a[x][y]]-1]=0;                 f[a[x][y]]=0;             }             return;         }         dfs(x+1,y);         return;     }     if (x==2){         if (!f[a[x][y]]){             f[a[x][y]]=(f[a[0][y]]-1+f[a[1][y]]-1+jw[y+1])%n+1;             if (!g[f[a[x][y]]-1]){                 g[f[a[x][y]]-1]=1;                 jw[y]=(jw[y+1]+f[a[0][y]]-1+f[a[1][y]]-1)/n;                 dfs(0,y-1);                 g[f[a[x][y]]-1]=0;             }             f[a[x][y]]=0;             return;         }         if ((f[a[0][y]]-1+f[a[1][y]]-1+jw[y+1])%n==f[a[2][y]]-1){             jw[y]=(jw[y+1]+f[a[0][y]]-1+f[a[1][y]]-1)/n;             dfs(0,y-1);         }         return;     } } void read() {     scanf("%d",&n);     for (int i=0; i<3; i++){         while (ch<'A' || ch>'Z') ch=getchar();         for (int j=1; j<=n; j++) a[i][j]=ch-'A',ch=getchar();     } } int main(){ 	read();     dfs(0,n);     return 0; }

我这样的算法并不是最好的但是还可以,还可以四步四步算,五步五步算......但是有一种更好的方法――高斯消元,不会,所以没打。

谢谢!



文章来源: 虫食算(搜索)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!