C语言洛谷题目分享(7)PERKET和火柴棒等式

目录

1.前言

2.俩道题目

1.火柴不等式

1.题目描述

2.输入格式

3.输出格式

4.输入输出样例

5.说明

6.题解

2.PERKET

1.题目描述

2.输入格式

3.输出格式

4.输入输出样例

5.说明

6.题解

3.小结


1.前言

哈喽大家好啊,今天继续为大家分享俩道洛谷dfs的经典题目,希望能对大家有所帮助。

2.俩道题目

1.火柴棒等式

1.题目描述

给你 n 根火柴棍,你可以拼出多少个形如 A+B=C 的等式?等式中的 A、B、C 是用火柴棍拼出的整数(若该数非零,则最高位不能是 0)。用火柴棍拼数字 0∼9的拼法如图所示:

注意:

  1. 加号与等号各自需要两根火柴棍;
  2. 如果 A≠B,则 A+B=C 与 B+A=C 视为不同的等式(A,B,C≥0);
  3. 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.小结

今天的分享到在这里就结束咯~,希望大家多多鼓励我这样我就可以产出更多更有价值的内容啦~

  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃烤鸡翅的酸菜鱼

希望大家对我多多支持喔~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值