解题思路
40分:暴力搜索每个字母代表的数
考虑剪枝 (搜索字母的顺序按竖式的从右到左,方便剪枝)
每搜索一个字母时,其实已经可以判断竖式的可行性了
- 当竖式上当前位的右边都有时,
(
a
+
b
)
( a + b ) % n < > c
(a+b)不可行(加数
x
,
y
x , y
x,y和
z
z
z)。
但是还要考虑进位,设右边进位 t t t, ( a + b + t ) ( a + b+ t ) % n < > c (a+b+t)不可行 - 当竖式上当前位的右边有字母没有搜索时,无法判断有没有进位
但是加法中的进位最多为1,即当 ( a + b ) ( a + b ) % n < > z (a+b)且 ( a + b + 1 ) ( a + b + 1 ) % n < > z (a+b+1) 不可行 - 当前位已是第一位,但是依然有进位, ( i = = 1 ) ( i = = 1 ) (i==1)且 ( a + b ) / n > 0 ( a + b) / n > 0 (a+b)/n>0不可行
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
bool flag=0;
int ans[50],v[50],kj[50],lyx[50],n,m;
string s[3];
bool check(){//判断可行性
int t=0;
for(int i=n-1; i>=0; i--)
{
int a=ans[s[0][i]-64],b=ans[s[1][i]-64],c=ans[s[2][i]-64];
if(a!=-1&&b!=-1&&c!=-1)
{
if(t!=-1)
{
if((a+b+t)%n!=c)return 0;//1
if(i==0&&(a+b+t)/n)return 0;//3
t=(a+b+t)/n;
}
else
{
if((a+b)%n!=c&&(a+b+1)%n!=c)return 0;//1,2
if(i==0&&(a+b)/n)return 0;//3
}
}
else t=-1;//当前位有字母还没搜索,进位设为-1
}
return 1;
}
void dfs(int dep){
if(flag==1)
return;
if(dep>n)
{
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
flag=1;
return;
}
for(int i=0;i<n;i++)
{
if(!v[i])//搜索每个字母可用数字
{
v[i]=1;
ans[lyx[dep]]=i;
if(check())
dfs(dep+1);
v[i]=0;
ans[lyx[dep]]=-1;
}
}
}
int main()
{
scanf("%d",&n);
for(int i=0; i<=2; i++)
cin>>s[i];
for(int j=n-1; j>=0; j--)//从右到左
for(int i=0; i<=2; i++)
{
{
if(!v[s[i][j]-64])
{
v[s[i][j]-64]=1;
lyx[++m]=s[i][j]-64;//字母按出现顺序记录
}
}
}
memset(ans,-1,sizeof(ans));
memset(v,0,sizeof(v)); //懒得多建一个数组,重新利用
dfs(1);
}