2022/12/28总结

一:PERKET

题目描述:

Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 nn 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 ss 和苦度 bb。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。

众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。

另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。

输入格式

第一行一个整数 nn,表示可供选用的食材种类数。

接下来 nn 行,每行 22 个整数 s_isi​ 和 b_ibi​,表示第 ii 种食材的酸度和苦度。

输出格式

一行一个整数,表示可能的总酸度和总苦度的最小绝对差。

题解:

1:设置函数i是表示目前的配料编号,x为酸度,y为甜度

2:注意,必须大于n才表示全部搜完

3:判断清水的情况

4:分两种情况搜索:1添加 2不添加

5:更新数据

代码:

#include<stdio.h>
int a[100],b[100],n,ans=10000;
void dfs(int i,int x,int y){//i是表示目前的配料编号,x为酸度,y为甜度
    if(i>n){
        if(x==1&&y==0)return;//判断清水的情况
        ans=min(abs(x-y),ans);//更新ans
        return;
    }
    dfs(i+1, x*=a[i], y+=b[i]); //分两种情况搜索:1添加 2不添加
    dfs(i+1,x/=a[i],y-=b[i]);
}
int min(int a,int b)
{
    if(a<b)return a;
    else return b;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d %d",&a[i],&b[i]);
    }
    dfs(1,1,0);
    printf("%d\n",ans);
    return 0;
}

二:考前临时抱佛脚

题目描述

这次期末考试,kkksc03 需要考 44 科。因此要开始刷习题集,每科都有一个习题集,分别有 s_1,s_2,s_3,s_4s1​,s2​,s3​,s4​ 道题目,完成每道题目需要一些时间,可能不等(A_1,A_2,\ldots,A_{s_1}A1​,A2​,…,As1​​,B_1,B_2,\ldots,B_{s_2}B1​,B2​,…,Bs2​​,C_1,C_2,\ldots,C_{s_3}C1​,C2​,…,Cs3​​,D_1,D_2,\ldots,D_{s_4}D1​,D2​,…,Ds4​​)。

kkksc03 有一个能力,他的左右两个大脑可以同时计算 22 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。

由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。

输入格式

本题包含 55 行数据:第 11 行,为四个正整数 s_1,s_2,s_3,s_4s1​,s2​,s3​,s4​。

第 22 行,为 A_1,A_2,\ldots,A_{s_1}A1​,A2​,…,As1​​ 共 s_1s1​ 个数,表示第一科习题集每道题目所消耗的时间。

第 33 行,为 B_1,B_2,\ldots,B_{s_2}B1​,B2​,…,Bs2​​ 共 s_2s2​ 个数。

第 44 行,为 C_1,C_2,\ldots,C_{s_3}C1​,C2​,…,Cs3​​ 共 s_3s3​ 个数。

第 55 行,为 D_1,D_2,\ldots,D_{s_4}D1​,D2​,…,Ds4​​ 共 s_4s4​ 个数,意思均同上。

题解:

1:利用背包算法

2:如果一个科目中只有一个题目,那么这一科的时间就是这个题目的时间;如果这个科目中有两个题目,那么这一科的时间就是这两个题目时间中较大的那一个。
当这个科目中的题目大于两道时,设这个科目的总时间是t,那么最优时间是t/2,也就是同时做两个科目的时间差为0。

代码:

#include<stdio.h>
int a,b,c,d;//对应s1,s2,s3,s4
int ans;//最后消耗的总时间
int fun(int a){//背包算法
	int a1[25],f[2000]={0};
	int m=0;//m求出总时间
	for(int i=0;i<a;i++) {
    scanf("%d",&a1[i]),m+=a1[i];}
	if(a==1) return a1[0];	//如果只有一个题目
	else if(a==2) return a1[1]>a1[0]?a1[1]:a1[0];	//有两个题目
	else {
		for(int i=0;i<a;i++){
			for(int j=m/2;j>=a1[i];j--){
				f[j]=max(f[j],f[j-a1[i]]+a1[i]);
			}
		}
		return max(f[m/2],m-f[m/2]);
	}

}
int max(int a,int b)
{
    if(a>b) return a;
    else return b;
}
int main(){
	scanf("%d %d %d %d",&a,&b,&c,&d);
	ans=fun(a)+fun(b)+fun(c)+fun(d);
	printf("%d",ans);
	return 0;
}

知识点:

背包

 一、01背包

这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放
用子问题定义状态:即f[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值。

则其状态转移方程便是:

f[i][j] = max( f[i-1] [j], f[i-1][j-w[]] + o[i])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值