题目描述 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);
}