【YBT高效进阶】1基础算法/4深度优先搜索/3虫食算

【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;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/115218224