PERKET

 PERKET

## 题目描述

Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s 和苦度 b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。
众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。
另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。

## 输入格式
第一行一个整数 n,表示可供选用的食材种类数。
接下来 n 行,每行 2 个整数 si 和 bi,表示第 i 种食材的酸度和苦度。

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


### 样例输入 #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 <= n <= 10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1e9 ,酸度和苦度不同时为 1 和 0 。

方法一:dfs  (回溯)

#include <bits/stdc++.h>   //简单的dfs,就不多解释了
using namespace std;
#define int long long 
const int N=12;
int ans=0x3f3f3f3f;
int s[N],b[N];
bool vis[N];
int n,x=1,y=0;    //初始化
void dfs(int u)
{
    if (u>=n) return ;
    for (int i=0;i<n;i++)
    {
        if (!vis[i])
        {
            x *=s[i];
            y +=b[i];
            ans=min(ans,abs(x-y));
            vis[i]=1;      
            dfs(u+1);

            vis[i]=0;      //恢复现场哦!
            x /=s[i];
            y -=b[i];
        }
    }
}
signed main()
{
    cin>>n;
    for (int i=0;i<n;i++) cin>>s[i]>>b[i];
    dfs(0);
    cout<<ans;
    return 0;

方法二:dfs (不用回溯)

#include <bits/stdc++.h>   
using namespace std;
#define int long long 
const int N=12;
int ans=0x3f3f3f3f;
int s[N],b[N];
int n;
void dfs(int u,int x,int y)
{
    if (u>=n)           
    {
        if (x==1&&y==0) return ;    //判断是否为清水
        ans=min(ans,abs(x-y));
        return ;
    }
    dfs(u+1,x*s[u],y+b[u]);       //2种情况,选与不选
    dfs(u+1,x,y);
}
signed main()
{
    cin>>n;
    for (int i=0;i<n;i++) cin>>s[i]>>b[i];
    dfs(0,1,0);
    cout<<ans;
    return 0;
}

方法三:位运算   (纯纯暴力)

//位运算,用二进制数表示配料的选择情况,例如有5种配料,二进制数01101则表示选择第1、3、4种配料(从右往左)
//一共有(1<<n-1)-1种选法
#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int N=12;
int ans=0x3f3f3f3f;      //初始化
int s[N],b[N];
signed main()
{
    int n;
    cin>>n;
    for (int i=0;i<n;i++) cin>>s[i]>>b[i];
    for (int i=1;i<1<<n;i++)  //至少选择一种,不能为清水
    {
        int x=1,y=0;
        for (int j=0;j<n;j++)
        {
            if ((i>>j)&1)       //判断第j的位置是否为1,即是否选择
            {
                x *=s[j];
                y +=b[j];
            }
        }
        ans=min(ans,abs(x-y));
    }
    cout<<ans;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值