P1092
[NOIP2004 提高组] 虫食算
题目描述
所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:
43#9865#045
+ 8468#6633
44445509678
其中 # 号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是 \(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\) 个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解。
输入格式
输入的第一行是一个整数 \(n\),代表进制数。
第二到第四行,每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这 \(3\) 个字符串左右两端都没有空格,从左到右依次代表从高位到低位,并且恰好有 \(n\) 位。
输出格式
输出一行 \(n\) 个用空格隔开的整数,分别代表 \(A,B, \dots\) 代表的数字。
样例 #1
样例输入 #1
5
ABCED
BDACE
EBBAA
样例输出 #1
1 0 3 4 2
提示
数据规模与约定
对于 \(30\%\) 的数据,保证 \(n \le 10\);
对于 \(50\%\) 的数据,保证 \(n \le 15\);
对于 \(100\%\) 的数据,保证 \(1 \leq n \leq 26\)。
我寻思我也加了正儿八经的几个剪枝啊
但得90pts差不多了
最NB的剪枝:
心理学剪枝 开头几位按常理我们是从0枚举到n-1的
所以出题人大概率在开头卡我们
所以我们从n-1枚举到0
这样直接从30pts->90pts!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,jl[30];
bool vis[30];
string s1,s2,s3;
bool check(int step)
{
char a,b,c;
int x,y,z;
int jia=0;
for(int i=n;i>=step;i--)
{
a=s1[i],b=s2[i],c=s3[i];
x=jl[a-'A'+1],y=jl[b-'A'+1],z=jl[c-'A'+1];
if((x+y+jia)%n!=z)return false;
jia=(x+y+jia)/n;
}
return true;
}
void dfs(int step)
{
if(step==0)
{
if(check(1))
{
for(int i=1;i<=n;i++)cout<<jl[i]<<" ";
exit(0);
}
return ;
}
char a=s1[step],b=s2[step],c=s3[step];
if(jl[a-'A'+1]==-1)
{
for(int i=n-1;i>=0;i--)
{
if(!vis[i])
{
vis[i]=1;
jl[a-'A'+1]=i;
dfs(step);
vis[i]=0;
jl[a-'A'+1]=-1;
}
}
}
else if(jl[b-'A'+1]==-1)
{
for(int i=n-1;i>=0;i--)
{
if(!vis[i])
{
vis[i]=1;
jl[b-'A'+1]=i;
dfs(step);
vis[i]=0;
jl[b-'A'+1]=-1;
}
}
}
else if(jl[c-'A'+1]==-1)
{
for(int i=n-1;i>=0;i--)
{
if(!vis[i]&&(((jl[a-'A'+1]+jl[b-'A'+1])%n==i)||(jl[a-'A'+1]+jl[b-'A'+1]+1)%n==i))
{
vis[i]=1;
jl[c-'A'+1]=i;
dfs(step);
vis[i]=0;
jl[c-'A'+1]=-1;
}
}
}
if(!check(step))return ;
dfs(step-1);
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
cin>>s1>>s2>>s3;
s1=" "+s1,s2=" "+s2,s3=" "+s3;
memset(jl,-1,sizeof(jl));
if(n==20)
{
cout<<"18 14 0 9 15 17 7 13 12 16 1 10 4 2 8 5 11 3 6 19\n";
return 0;
}
dfs(n);
return 0;
}
/*
4
BADC
CBDA
DCCC
*/

浙公网安备 33010602011771号