【ybt】【基算 深搜 课过 例3】虫食算

虫食算

题目链接:虫食算
感谢 @ l z h @lzh @lzh 大佬的帮助


题目描述

在这里插入图片描述
在这里插入图片描述

解题思路

很明显这是一道深搜题 (不然它怎么会归到深搜专栏里呢)

可以搜索枚举每一个字母来寻找最佳答案。

但这样是 O ( 1 0 n ) O(10^n) O(10n) 的时间复杂度,肯定是过不了的,所以要加入剪枝。

如果当前情况已经不合法了,自然不能搜下去。

那么现在关键在于 c h e c k ( ) check() check() 函数。

如果当前位三个数都被搜到过了,那么直接判断即可。但如果上一位有数未知,那么最多还可以对这一位贡献 1 1 1

最后一位要特判:无论是进位或者不等都是不合法的。

code

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;

int n,tot,ok;
int v[30];
int b[20];
int ans[30];
char ss[30];
string s[4];

int check()
{
    
    
	int t=0;
	for(int i=n-1;i>=0;i--)
	{
    
    
		int a=ans[s[1][i]-'A'];
		int b=ans[s[2][i]-'A'];
		int c=ans[s[3][i]-'A'];
		if(a!=-1&&b!=-1&&c!=-1)
		{
    
    
			if(t!=-1)
			{
    
    
				if((a+b+t)%n!=c)
					return 0;
				if(i==0&&a+b+t>=n)
					return 0;
				t=(a+b+t)/n;
			}
			else
			{
    
    
				if((a+b)%n!=c&&(a+b+1)%n!=c)
					return 0;
				if(i==0&&a+b>=n)
					return 0;
			}
		}
		else
			t=-1;
	}
	return 1;
}

void dfs(int dep)
{
    
    
	if(ok)
		return;
	if(dep>n)
	{
    
    
		ok=1;
		for(int i=0;i<n;i++)
			cout<<ans[i]<<" ";
		return;
	}
	for(int i=0;i<n;i++)
	{
    
    
		if(!b[i])
		{
    
    
			b[i]=1;
			ans[ss[dep]-'A']=i;
			if(check())
				dfs(dep+1);
			b[i]=0;
			ans[ss[dep]-'A']=-1;
		}
		
	}
}

int main()
{
    
    
	cin>>n;
	cin>>s[1]>>s[2]>>s[3];
	for(int i=n-1;i>=0;i--)
		for(int j=1;j<=3;j++)
			if(!v[s[j][i]-'A'])
			{
    
    
				v[s[j][i]-'A']=1;
				ss[++tot]=s[j][i];
			}
	memset(ans,-1,sizeof(ans));
	dfs(1);
}

猜你喜欢

转载自blog.csdn.net/SSL_guyixin/article/details/112131652