CODEVS1064虫食算noip提高组T4

题目描述  Description

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

       43#9865#045
    +    8468#6633
       44445506978

    其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是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个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解,

思路:看到题后,就想到了按位搜索,从最低位到最高位,每次搜索都有三种情况(两加数都已有值、一个有、都没有),每种情况又有和有无值得两种情况(我比较丧病,就只想到了这种做法。。。),然后搜索就能过8个点(但是有一个小小的蛋疼的问题,导致我第一次只得了60分,要在输出时判断g是否为0,若不是的话就不满足了)。
加了一个剪枝:没一次进行递归之前都要将比i高的位数都判断一遍,一个judge解决,但是又有一个蛋疼的问题,就是不能只考虑加数加加数等于和的情况,也要考虑加数加加数加1等于和的情况,毕竟会有进位。。。

code:
(写了一个二百行的code,真是醉了。。。)

#include<iostream>

#include<cstring>

#include<cstdio>

using namespace std;

int ans[30]={0},a[30]={0},b[30]={0},c[30]={0},n;

bool f[30]={false},ff=false;

bool judge(int i)

{

int j;

for (j=i+1;j<=n;++j)

{

if (ans[a[j]]!=-1&&ans[b[j]]!=-1&&ans[c[j]]!=-1)

  if ((ans[a[j]]+ans[b[j]])%n!=ans[c[j]]&&(ans[a[j]]+ans[b[j]]+1)%n!=ans[c[j]])

    return true;

}

return false;

}

void work(int i,int g)

{

int j,k,x,y,z,he;

if (i>n&&g==0)

{

for (j=1;j<=n-1;++j)

  cout<<ans[j]<<" ";

cout<<ans[n]<<endl;

ff=true;

return;

}

x=a[i];y=b[i];z=c[i];

if (ans[x]!=-1&&ans[y]!=-1)

{

he=ans[x]+ans[y]+g;

if (he%n==ans[z]&&ans[z]!=-1) work(i+1,he/n);

if (ans[z]==-1)

{

if (!f[he%n])

{

ans[z]=he%n;

f[he%n]=true;

if (!judge(i)) 

  work(i+1,he/n);

if (ff) return;

ans[z]=-1;

f[he%n]=false;

}

}

}

else

{

if (ans[x]==-1&&ans[y]==-1)

{

for (j=0;j<n;++j)

{

if (!f[j])

{

for (k=0;k<n;++k)

  if (!f[k])

    {

 he=j+k+g;

 if (ans[z]==-1)

 {

  if (!f[he%n])

  {

     ans[z]=he%n;

     ans[x]=j;

           ans[y]=k;

     f[j]=true;

     f[k]=true;

               f[he%n]=true;

               if (!judge(i)) 

                 work(i+1,he/n);

               if (ff) return;

               ans[z]=-1;

               ans[x]=-1;

               ans[y]=-1;

               f[he%n]=false;

   f[j]=false;

   f[k]=false;

  }

 }

 else

 {

   if (he%n==ans[z]) 

  {

     ans[x]=j;

             ans[y]=k;

             f[j]=true;

       f[k]=true;

       if (!judge(i))

     work(i+1,he/n);

   if (ff) return;

   ans[x]=-1;

             ans[y]=-1;

             f[j]=false;

       f[k]=false;

   }

 }

  }

}

            }

}

else

{

if ((ans[x]==-1&&ans[y]!=-1)||(ans[x]!=-1&&ans[y]==-1))

{

if (ans[x]!=-1)

{

j=x;x=y;y=j;

}

for (j=0;j<n;++j)

{

if (!f[j])

{

he=ans[y]+j+g;

if (ans[z]!=-1)

{

 if (he%n==ans[z]) 

 {

   ans[x]=j;

   f[j]=true; 

   if (!judge(i))

     work(i+1,he/n);

   if (ff) return;

   f[j]=false;

   ans[x]=-1;

 } 

}

else

{

    if (!f[he%n])

  {

     ans[z]=he%n;

     ans[x]=j;

     f[j]=true;

               f[he%n]=true;

               if (!judge(i))

                 work(i+1,he/n);

               if (ff) return;

               ans[z]=-1;

               ans[x]=-1;

               f[j]=false;

               f[he%n]=false;

  }

}

}

}

}

}

}

if (ff) return;

}

int main()

{

int i,j;

char ch;

cin>>n;

for (i=1;i<=n;++i)

{

cin>>ch;

a[n-i+1]=ch-'A'+1;

}

for (i=1;i<=n;++i)

{

cin>>ch;

b[n-i+1]=ch-'A'+1;

}

for (i=1;i<=n;++i)

{

cin>>ch;

c[n-i+1]=ch-'A'+1;

    }

for (i=1;i<=n;++i)

  ans[i]=-1;

work(1,0);

你可能感兴趣的:(code)