题目描述
[COCI2008-2009 #2] PERKET
洛谷p2036
题目描述
Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 $n$ 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 $s$ 和苦度 $b$。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。
众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。
另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。
输入格式
第一行一个整数 $n$,表示可供选用的食材种类数。
接下来 $n$ 行,每行 $2$ 个整数 $s_i$ 和 $b_i$,表示第 $i$ 种食材的酸度和苦度。
输出格式
一行一个整数,表示可能的总酸度和总苦度的最小绝对差。
样例 #1
样例输入 #1
1
3 10
样例输出 #1
7
样例 #2
样例输入 #2
2
3 8
5 8
样例输出 #2
1
样例 #3
样例输入 #3
4
1 7
2 6
3 8
4 9
样例输出 #3
1
提示
数据规模与约定
对于 $100\%$ 的数据,有 $1 \leq n \leq 10$,且将所有可用食材全部使用产生的总酸度和总苦度小于 $1 \times 10^9$,酸度和苦度不同时为 $1$ 和 $0$。
最简单最好理解的暴力dfs
每个调料品都有选 or 不选俩种状态
所以是指数型dfs搜索
时间复杂度O(2^n)
C++ 代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int , int> PII;
const int N = 10;
int arr[N]; //0表示未知; 1表示选; 2表示不选;
int acid[N];
int bitter[N];
int n;
int taste = 1e9;
void dfs(int x)
{
//不存在一种不需要配料构成的食物
if(x > n)
{
int flag = false;
for(int i = 1; i <= n; i++)
{
if(arr[i] != 2) flag = true;
}
//所以当dfs出来的结果为22222...
//直接剪枝
if(!flag) return;
int sum_acid = 1;
int sum_bitter = 0;
for(int i = 1; i <= n; i++)
{
//表示这种配料要选
if(arr[i] == 1)
{
sum_acid *= acid[i];
sum_bitter += bitter[i];
}
}
//酸度和苦度的绝对差
int sum = abs(sum_acid - sum_bitter);
taste = min(sum , taste);
return;
}
//每种配料都有选和不选俩种情况
//选
arr[x] = 1;
dfs(x + 1);
arr[x] = 0;
//不选
arr[x] = 2;
dfs(x + 1);
arr[x] = 0;
}
int main()
{
cin>>n;
for(int i = 1; i <= n; i++) cin>>acid[i]>>bitter[i];
dfs(1);
cout<<taste<<endl;
return 0;
}