P1092 虫食算 题解(搜索)

题目链接

P1092 虫食算

解题思路

好题啊!这个搜索好难写......

大概是要考虑进位和考虑使用过某个数字这两个东西,但就很容易出错......

首先这个从后往前搜比较好想,按照从后往前出现的顺序搜,在这个剪枝条件下速度会快很多。

比如样例,

5
ABCED
BDACE
EBBAA

从右往左出现的次序是\(DEAECACABBDBABE\),去重之后是\(DEACB\),这就是要搜索的顺序,用\(seq\)记录。

当某时候等式明显已经不满足时,就直接\(return\)

还有别的剪枝,但这样直接能\(79ms\)。没必要。

AC代码

#include
#include
#define N 30
int n,a[N],b[N],c[N],vis[N],ans[N];
char s[3][N];
int seq[N];//搜索顺序 
void dfs(int x){//搜到第x个元素 
	int i,jw=0;
	if(ans[a[0]]+ans[b[0]]>=n)return;
	for(i=n-1;i>=0;i--){//从后往前检查 
		int A=ans[a[i]],B=ans[b[i]],C=ans[c[i]];
		if(A==-1||B==-1||C==-1)continue;
		if((A+B+1)%n!=C&&(A+B)%n!=C)return;
	}
	if(x==n){
		for(i=n-1;i>=0;i--){
			int A=ans[a[i]],B=ans[b[i]],C=ans[c[i]];
			if((A+B+jw)%n!=C)return;
			jw=(A+B+jw)/n;
		}
		for(i=0;i=0;i--){
		if(!vis[i]){
			vis[i]=1;ans[seq[x]]=i;
			dfs(x+1);
			vis[i]=0;ans[seq[x]]=-1;
		}
	}
}
int cnt;
void f(int x){//提供搜索顺序,加快搜索速度 
	if(!vis[x]){vis[x]=1;seq[cnt++]=x;}
}
int main(){
	int i;
	for(i=0;i<30;i++)ans[i]=-1;
	scanf("%d%s%s%s",&n,s[0],s[1],s[2]);
	for(i=0;i=0;i--){f(a[i]);f(b[i]);f(c[i]);}
	for(i=0;i

这是seq优化后的结果:

P1092 虫食算 题解(搜索)_第1张图片

这是从n-1到1搜索的结果:

P1092 虫食算 题解(搜索)_第2张图片

而这是从1到n-1搜索的结果:

P1092 虫食算 题解(搜索)_第3张图片

你可能感兴趣的:(P1092 虫食算 题解(搜索))