虫食算

来源:互联网 发布:la域名在里注册便宜 编辑:程序博客网 时间:2024/06/06 02:43


虫食算    描述 Description  所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:
     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个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解       输入格式 Input Format  输入包含4行。第一行有一个正整数N(N<=26),后面的3行每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有N位。   

    输出格式 Output Format  输出包含一行。在这一行中,应当包含唯一的那组解。解是这样表示的:输出N个数字,分别表示A,B,C……所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。  输入输入:

5
ABCED
BDACE
EBBAA

输出:

1 0 3 4 2


最基本的搜索,按合理的搜索顺序(从后向前),精妙的剪枝(三个确定两个,判断。一个数之前用过,退出。第一个等于第三个,第二个则等于0或n-1...)就可以AC了

半AC代码:


#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<algorithm>#include<cmath>using namespace std;string s1,s2,s3;int n,a[30],b[50]={};int c[30]={},d[30]={};int dfs(int k);int lll(int ch1,int ch2,int ch3,int k){if(c[ch3]==1){if((a[ch1]+a[ch2]+b[k])%n!=a[ch3])    return 0;b[k-1]=(a[ch1]+a[ch2]+b[k])/n;dfs(k-1);}else{a[ch3]=(a[ch1]+a[ch2]+b[k])%n;b[k-1]=(a[ch1]+a[ch2]+b[k])/n;if(d[a[ch3]]==1){b[k-1]=0;return 0;}c[ch3]=1;d[a[ch3]]=1;dfs(k-1);c[ch3]=0;d[a[ch3]]=0;a[ch3]=-1;}return 0;}int dfs(int k){    if(k==-1&&b[k]==0)    {for(int i=0;i<n;i++)cout<<a[i]<<' ';cout<<endl;/*for(int i=0;i<n;i++)cout<<b[i]<<' ';*/exit(0);    }int ch1=s1[k]-'A';int ch2=s2[k]-'A';int ch3=s3[k]-'A';    if(c[ch1]==1&&c[ch2]==1)    {        lll(ch1,ch2,ch3,k);/*if(c[ch3]==1)        {            if((a[ch1]+a[ch2]+b[k])%n!=a[ch3])    return 0;            b[k-1]=(a[ch1]+a[ch2]+b[k])/n;            dfs(k-1);        }        else        {            a[ch3]=(a[ch1]+a[ch2]+b[k])%n;            b[k-1]=(a[ch1]+a[ch2]+b[k])/n;            if(d[a[ch3]]==1)            {b[k-1]=0;                return 0;            }            c[ch3]=1;            d[a[ch3]]=1;            dfs(k-1);            c[ch3]=0;            d[a[ch3]]=0;            a[ch3]=-1;        }*/    }    else {if(c[ch1]==1&&c[ch2]!=1){/*if(c[ch3]==1){a[ch2]=a[ch3]-b[k]-a[ch1];if(a[ch2]<0)a[ch2]+=n;if(d[a[ch2]]==1){a[ch2]=-1;return 0;}c[ch2]=1;d[a[ch2]]=1;dfs(k-1);c[ch2]=0;d[a[ch2]]=0;a[ch2]=-1;goto trans;}*/            for(int i=n-1;i>=0;i--)            {                if(d[i]!=1)                {                    d[i]=1;                    a[ch2]=i;                    c[ch2]=1;                    //dfs(k);lll(ch1,ch2,ch3,k);                    d[i]=0;                    a[ch2]=-1;                    c[ch2]=0;                }            }trans:{}}else {if(c[ch2]==1&&c[ch1]!=1){/*if(c[ch3]==1){a[ch1]=a[ch3]-b[k]-a[ch2];if(a[ch1]<0)a[ch1]+=n;if(d[a[ch1]]==1){a[ch1]=-1;return 0;}c[ch1]=1;d[a[ch1]]=1;dfs(k-1);d[a[ch1]]=0;c[ch1]=0;a[ch1]=-1;goto trans1;}*/for(int i=n-1;i>=0;i--){if(d[i]!=1){d[i]=1;c[ch1]=1;a[ch1]=i;//dfs(k);lll(ch1,ch2,ch3,k);d[i]=0;c[ch1]=0;a[ch1]=-1;}}trans1:{}}else {for(int i=n-1;i>=0;i--)if(d[i]!=1) {d[i]=1;c[ch1]=1;a[ch1]=i;dfs(k);//lll(ch1,ch2,ch3,k);a[ch1]=-1;d[i]=0;c[ch1]=0;}}}}return 0;}int main(){    //freopen("a.in","r",stdin);    //freopen("a.out","w",stdout);    memset(a,-1,sizeof(a));cin>>n;cin>>s1>>s2>>s3;    dfs(n-1);    return 0;}
为什么是半AC呢?因为在洛谷上提交有一测试点过不了,可是在本校oj上AC了...

垃圾本校OJ,吃枣药丸

然而...

洛谷上还没有过...



0 0
原创粉丝点击