【YBT高效进阶】1基础算法/4深度优先搜索/3虫食算
内存限制:256 MiB
时间限制:1000 ms
标准输入输出
题目类型:传统
评测方式:文本比较
题目描述
所谓虫食算,就是原先的算是中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定啃掉的字母。来看一个简单的例子:
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 个用空格隔开的整数,分别表示 A,B… 代表的数字。
样例
样例输入
5
ABCED
BDACE
EBBAA
样例输出
1 0 3 4 2
数据范围与提示
对于 30% 的数据,保证 n<=10。
对于 50% 的数据,保证 n<=15。
对于 100% 的数据,保证 1<=n<=26。
思路
从右往左dfs搜索每个数,
每搜索一个数就check一下
1.若右边所有数确定,(a+b+g)%n!=c,return 0;
2.若右边有数不确定,(a+b)%n!=c&&(a+b+1)%n!=c,return 0;
3.若是最高位,a+b+g>=n或a+b>=n,return 0;
代码
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int n,tot,num[27];
char str[4][27],zm[27];
bool vis[27],use[27];
bool check()
{
int g=0,a,b,c,i;
for(i=n-1;i>=0;i--)
{
a=num[str[0][i]-'A'];
b=num[str[1][i]-'A'];
c=num[str[2][i]-'A'];
if(a>-1&&b>-1&&c>-1)
{
if(g==-1)
{
if(((a+b)%n!=c&&(a+b+1)%n!=c)||(i==0&&a+b>=n))return 0;
}
else
{
if((i==0&&a+b+g>=n)||((a+b+g)%n!=c))return 0;
g=(a+b+g)/n;
}
}
else g=-1;
}
return 1;
}
bool DFS(int dep)
{
if(dep>tot)return 1;
for(int i=0;i<n;i++)
if(!use[i])
{
num[zm[dep]-'A']=i,use[i]=1;
if(check()&&DFS(dep+1))return 1;
num[zm[dep]-'A']=-1,use[i]=0;
}
return 0;
}
int main()
{
int i,j;
ios::sync_with_stdio(false);
memset(num,-1,sizeof(num));
memset(vis,0,sizeof(vis));
memset(use,0,sizeof(use));
cin>>n>>str[0]>>str[1]>>str[2];
for(i=n-1;i>=0;i--)
{
if(!vis[str[0][i]-'A'])vis[str[0][i]-'A']=1,zm[++tot]=str[0][i];
if(!vis[str[1][i]-'A'])vis[str[1][i]-'A']=1,zm[++tot]=str[1][i];
if(!vis[str[2][i]-'A'])vis[str[2][i]-'A']=1,zm[++tot]=str[2][i];
}
for(DFS(1),i=0;i<n;i++)cout<<num[i]<<' ';
return 0;
}