P1092 虫食算
Posted lpf-666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1092 虫食算相关的知识,希望对你有一定的参考价值。
P1092 虫食算
DFS+剪枝
题意描述
有一个好好的算式突然被一只虫子给啃了,而且什么也没剩下,
然后我们莫名其妙的知道了哪些数是相同的,问各字母代表的数字,
数据保证有且仅有一组解,没了。
还看不懂的话,出门右手进传送门
算法分析
如果你很忙,请跳过下面3行
题意描述的比较简单,但也不是不能理解(语文不好)
看一看数据范围,发现n≤26,然后大喊三声:“爆搜!!!”
过了15分钟,你又喊道:“妈妈我TLE啦!!!”
初步分析
首先设计状态,搜索的深度是确定的数的个数,当深度==n时表示确定了所有数(但并不保证答案正确)
显然如果爆搜你会TLE(2626是一个很有趣的数让你TLE的数),所以我们要考虑剪枝,
同时,搜索的顺序也耐人寻味,难道是按照A,B,C······这样搜索吗?
还有,检测答案的方法又是什么?
综上,我们需要考虑三个问题:
- 怎么剪枝?
- 怎么钦定搜索顺序?
- 怎么检测答案?
深入探索
剪枝
算是重点吧。
第一,三个字符串长度都是n,很容易想到不能有进位。
第二,首先我们看看这个 xx6xx
? + xx8xx
? ---------
? xx5xx
那么它是对是错?
- 如果按照常理,6+8=14!=5或15,这是错的
- 但如果上一位有进位,6+8+1=15,它又是合法的
所以有:如果某 (i) 位,满足 ((A[i]+B[i])%n!(=C[i])) && ((A[i]+B[i]+1))%n!(=C[i])
根据上面的分析,这种状态肯定不对,直接return
搜索顺序
小学生都知道的:从低位到高位搜(具体看代码)
检测答案
从低位到高位跑一遍等式即可(具体看代码)
代码实现
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int n,a[30],b[30],c[30];
int num[30],id[30],sum=0;
char aa[30],bb[30],cc[30];
bool use[30];
void Get(int x){
if(!use[x]){
use[x]=true;
id[sum++]=x; <————搜索顺序预处理
}
return;
}
bool check(){
for(int i=n,p=0;i>=1;i--){
int A=num[a[i]],B=num[b[i]],C=num[c[i]];
if((A+B+p)%n!=C) return false; <————检测答案
p=(A+B+p)/n;
}
return true;
}
void print(){
for(int i=1;i<=n;i++) printf("%d ",num[i]);
exit(0);
}
bool cut_down(){
if(num[a[1]]+num[b[1]]>=n) return true;
for(int i=n;i>=1;i--){
int A=num[a[i]],B=num[b[i]],C=num[c[i]]; <————剪枝
if(A==-1||B==-1||C==-1) continue;
if((A+B)%n!=C&&(A+B+1)%n!=C) return true;
}
return false;
}
void dfs(int x){
//for(int i=1;i<=n;i++) printf("%d ",num[i]);
//printf("
");
if(cut_down()) return;
if(x==n){
if(check()) print();
return;
}
for(int i=n-1;i>=0;i--){
if(!use[i]){
num[id[x]]=i;
use[i]=true;
dfs(x+1);
num[id[x]]=-1;
use[i]=false;
}
}
return;
}
int main(){
scanf("%d",&n);
cin>>aa>>bb>>cc;
for(int i=1;i<=n;i++){
a[i]=aa[i-1]-'A'+1;
b[i]=bb[i-1]-'A'+1;
c[i]=cc[i-1]-'A'+1;
num[i]=-1;
}
memset(use,false,sizeof(use));
for(int i=n;i>=1;i--){
Get(a[i]);Get(b[i]);Get(c[i]);
}
memset(use,false,sizeof(use));
dfs(0);
return 0;
}
结语
Dfs+剪枝
以上是关于P1092 虫食算的主要内容,如果未能解决你的问题,请参考以下文章