算法day2 dfs搜索2题
一 PERKET
当我们拿到这个题目的时候,确实郁闷到底该怎么做,首先我们看这个题目
题目中给我们提供了这么多个调料,这个调料有酸度和苦度,这些都是它的属性,但是我们是选择这个调料,那么就是对于一个调料有选择和不选择的情况,所以这个就是递归指数型枚举
分析:由每个调料有两个情况,选择和选择,得出为指数型枚举
由它所述可以得出两个条件
1 至少有一种调料
2 酸度与苦度的绝对值的差为最小
这个是我们在选取值得时候得条件,所以我们只需要根据这个条件和指数型枚举来写出算法
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 15;
int n; //表示可选择的调料数量
int res = 1e9;
int st [N]={0};//表示状态
int bit [N];//表示苦度
int sour[N];//表示酸度
void dfs(int x){
if(x>n){
bool input_tl = false;
int sumbit = 0;//表示苦度和
int sumsour = 1;//表示酸度和
for(int i=1;i<=n;i++){
if(st[i]==1){
input_tl=true;
sumbit +=bit [i];
sumsour*=sour[i];
}
}
if(input_tl){
res=min(res,abs(sumbit-sumsour));
}
return ;
}
//选择
st[x]=1;
dfs(x+1);
st[x]=0;
//不选择
st[x]=2;
dfs(x+1);
st[x]=0;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %d",&sour[i],&bit[i]);
}
dfs(1);
printf("%d",res);
return 0;
}
二 火柴等式

我们拿到这个题目先分析是组合枚举,排列枚举还是指数枚举
我们来分析
首先这个题目是需要算出这个数字的棒子的,那么会输入n,那我们的数字的总火柴棒就是n-4,因为加号和等号都是要算入到火柴里面的
然后我们就是可以得出,我们直接指数型枚举,然后把他放到数组里面,相加,看是否等于这个n-4就好了,这里我们不需要记忆数组
为什么不需要记忆数组?
因为我们等式可能会有相同数字相加,所以我们不需要记忆数组来规定这个选没选
所以我们得出了这个是指数型枚举
然后我们就分析条件
1 火柴数字相加等于n-4
2 1和2火柴相加等于3火柴就好了
我们这里是需要引入sum这个和得因为我们需要进行计算和,然后这个和我们可以拆掉那个数字,然后数字对应数组的元素的火柴个数就好了
#include<iostream>
using namespace std;
const int N = 10010;
int n;
int res=0;
int ans[N]={0};
int num[N]={6,2,5,5,4,5,6,3,7,6};
int col(int x){
if(num[x]) return num[x];
else{
int sumFire = 0;
while(x){
sumFire+=num[x%10];
x=x/10;
}
return sumFire;
}
}
void dfs(int x,int sum){
if(sum>n)return ;
if(x>3){
if(ans[1]+ans[2]==ans[3]&&sum==n){
res++;
}
return ;
}
for(int i=0;i<=1000;i++){
ans[x]=i;
dfs(x+1,sum+col(i));
ans[x]=0;
}
}
int main(){
scanf("%d",&n);
n-=4;
dfs(1,0);
printf("%d",res);
return 0;
}
总结
指数型枚举需要直到我们是选择还是进行枚举去算每一个的样例是否满足题目所对应的条件,我们要把抽象话具体,这样我们就可以大大提升我们对与题目的分析