P2036 [COCI2008-2009 #2] PERKET

 复制Markdown  展开

题目描述

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

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

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

输入格式

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

接下来 𝑛 行,每行 2 个整数 𝑠𝑖​ 和 𝑏𝑖​,表示第 𝑖 种食材的酸度和苦度。

输出格式

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

输入输出样例

输入 #1

1
3 10

输出 #1

7

输入 #2

2
3 8
5 8

输出 #2

1

输入 #3

4
1 7
2 6
3 8
4 9

输出 #3

1

说明/提示

数据规模与约定

对于 100% 的数据,有 1≤𝑛≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1×^{_{}}10^{_{9}},酸度和苦度不同时为 1 和 0。

思路

这道题也是可以使用dfs进行所有情况的遍历,不过这道题增加了点小难度,它没有限制达到目标所需的元素个数,所以我们需要从1遍历到 n,如何实现呢?只需设置一个全局变量point,在solve中增加一个for循环,point初始值为1,每次循环后就point++,这样就可以实现遍历1到 n 的元素次数。

再者就是当元素个数达到目标时,要判断是否满足条件:酸度和苦度的绝对差最小。对呀酸度,总的酸度为每一种配料的酸度总乘积;对于苦度,总的苦度为每一种配料的苦度的总和。

所以在if语句中再统计总酸度和总苦度,然后与最小值Min判断,求最小值。

在这里要提醒一下,这些食物是携带一酸度和一苦度的,同一行酸度和苦度不是分离的,我一开始以为是各算各的,想了很久最后在发现题目没审好( 所以还是要好好审题啊๛ก(ー̀ωー́ก) )

 好啦,接下来就是你们最关心的AC代码啦!

AC代码

#include<iostream>
#include<math.h>
using namespace std;
typedef long long ll;
ll dis = 0x3f3f3f3f;//设置个最大值
ll Min = 0x3f3f3f3f;
int point,n;
int vec[12][12];
int a[12];
void dfs(int step,int start) {
	if (step == point) {
		ll suan = 1;
		ll ku = 0;
		for (int i = 0; i < point; i++) {
			suan *= vec[a[i]][1];
			ku += vec[a[i]][2];
		}
		dis = abs(suan - ku);
		if (dis < Min) {
			Min = dis;
		}
		return;
	}
	for (int i = start; i <= n; i++) {
		a[step] = i;
		dfs(step + 1,i + 1);
		a[step] = 0;
	}
}
void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> vec[i][1] >> vec[i][2];//酸度和苦度
	}
	for (int i = 1; i <= n; i++) {
		point = i;
		dfs(0, 1);
	}
	cout << Min;
}
int main()
{
	int t = 1;
	cin.tie(0)->ios::sync_with_stdio(false);
	while (t--) {
		solve();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值