目录
1.前言
哈喽大家好啊,今天继续为大家分享俩道洛谷dfs的经典题目,希望能对大家有所帮助。
2.俩道题目
1.火柴棒等式
1.题目描述
给你 n 根火柴棍,你可以拼出多少个形如 A+B=C 的等式?等式中的 A、B、C 是用火柴棍拼出的整数(若该数非零,则最高位不能是 0)。用火柴棍拼数字 0∼9的拼法如图所示:
注意:
- 加号与等号各自需要两根火柴棍;
- 如果 A≠B,则 A+B=C 与 B+A=C 视为不同的等式(A,B,C≥0);
- n 根火柴棍必须全部用上。
2.输入格式
一个整数 n(1≤n≤24)。
3.输出格式
一个整数,能拼成的不同等式的数目。
4.输入输出样例
5.说明
【输入输出样例 1 解释】
2 个等式为 0+1=1 和 1+0=1。
【输入输出样例 2 解释】
9 个等式为
0+4=4、0+11=11、1+10=11、2+2=4、2+7=9、4+0=4、7+2=9、10+1=11、11+0=11。
6.题解
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=10010;
int n=0;
int nums[10010]={6,2,5,5,4,5,6,3,7,6};//存放0~9之间十个数的火柴数目
int arr[N];
int res=0;
//计算火柴数
int col(int y){
if(nums[y]>0){
return nums[y];
}
//计算数目大于等于十以上的火柴数
else {
int sumfire=0;
while(y){
sumfire+=nums[y%10];
y=y/10;
}
return sumfire;
}
}
void dfs(int x,int sum){
if(sum>n)return ;
if(x>3){
if(arr[1]+arr[2]==arr[3]&&sum==n){
res++;
}
return ;//判断条件同时满足等式加合成立以及火柴数目总和满足题意
}
for(int i=0;i<=1000;i++){
arr[x]=i;
dfs(x+1,sum+col(i));
arr[x]=0;
}
}
int main(){
scanf("%d",&n);
n-=4;
dfs(1,0);//开始搜索
printf("%d",res);
return 0;
}
整体思路就是把每一个等式都搜索一遍,然后通过等式是否成立以及火柴数总和(记得加上+与=的火柴数喔)这俩个判断条件来进行筛选,最后输出方案数。
tips:记得在dfs函数里面提前剪枝,否则时间上过不去。
这样这道题就完成了。
2.PERKET
1.题目描述
Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s 和苦度 b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。
众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。
另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。
2.输入格式
第一行一个整数 n,表示可供选用的食材种类数。
接下来 n 行,每行 2 个整数 si 和 bi,表示第 i 种食材的酸度和苦度。(那个i是下角标)
3.输出格式
一行一个整数,表示可能的总酸度和总苦度的最小绝对差。
4.输入输出样例
5.说明
对于 100% 的数据,有 1≤n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1×10的9次方,酸度和苦度不同时为 1 和 0。
6.题解
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=20;//题目给10我开到20
int n=0;
int res=100000000;//记录满足题意的最小解
int st[N];
int sour[N];//酸度
int xian[N];//咸度
void dfs(int x){
if(x>n){
bool tf=false;
int sum1=1;//酸度乘积
int sum2=0;//咸度加和
//判断接下来遍历到的调料是否被选取
for(int i=1;i<=n;i++){
if(st[i]==1){
tf=true;
sum1*=sour[i];
sum2+=xian[i];
}
}
if(tf){
res=min(res,abs(sum1-sum2));
}
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],&xian[i]);
}
dfs(1);
printf("%d",res);
return 0;
}
这道题跟上一道题的大概思路相似,只不过这道题是指数搜索(即每一个配料都有被选取和不被选取俩个选择,因此有n个调料就有2的n次方的选取方式),搜索完毕后再根据题目要求寻找酸度与咸度的最小绝对差咯~
tips:这道题的小坑是判断是否为被选中的配料时,那一个布尔类型的变量到底是设计为全局变量还是局部变量,这个对这道题的影响至关重要。
3.小结
今天的分享到在这里就结束咯~,希望大家多多鼓励我这样我就可以产出更多更有价值的内容啦~