虫食算
题目链接:虫食算
感谢 @ 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);
}