CF--C-- Party Lemonade(贪心)

题目链接:http://codeforces.com/problemset/problem/913/C

这道题的主要思想就是贪心,看着非常像DP

以至于我第一次写的时候误认为就是DP,和背包问题差不多

如果用背包的角度来看,背包需要开DP数组,这个数组大小是N x M (n是物品数量,m是容量大小)

这道题容量大小为1e9  明显开不了这么大的数组,虽然n很小,即使简化为一维数组,大小也还是M

此时的我还没有死心.....为什么不能用离散化一下?,但是仔细一想,离散化后数组大小还是不能变.....

好吧 换个思路

为了尽量的节约金钱,肯定是先选性价比高的产品了,那么首先按照性价比排个序,从大到小排序

这样,从第一个开始挑选,这样可以尽量的解决金钱

那么是如何进行挑选的?

1.先按照性价比最高的先装,如果能装满一瓶就继续装,如果不够一瓶,那么就先别装了,因为有可能下一种的饮料虽然性价比不高,但是架不住便宜,而且容量正好可以装剩下的。比如第一种容量为4,价钱为4,第二种容量为1,价钱为2,需要容量为5。有前面这种情况也肯定有装第二种还不如装第一种划算  比如:第一种容量为4,价钱为2,第二种容量为1,价钱为3,需要容量为5,这样答案就不同了。这时我们就要比较一下两种方案

2.会不会出现这种情况?

按照性价比最高的装了n瓶,第二种装了1瓶,但是这并不是最佳情况,第二种只装剩下的,还有很多剩余,并且剩余的容量比第一种的容量还大,这样可以第一种装n-1瓶,剩下的用第二种装,这样岂不是更美滋滋?

比如:第一种容量20,价格10,第二种容量30,价格16,现需要30容量的,如果按照上面的方法肯定是错误!!那么哪里错了???    

其实没有错误,不会有这种数据的!!!因为容量必定为2的倍数,换句话说,小容量是大容量的因子。通俗点讲,用多个小容量的可以拼凑出所有的大容量,这就导致,如果 小容量的性价比最高,那么比它容量大的其实都可以不用选,不用看了

正是因为这样,才保证上述挑选的正确性

如果条件换了,容量不再是2的倍数,而是和价钱一样,都是随意输入的,那么我目前也没有办法解决了,但是满足小容量是大容量的因子,这种方法都可以解决

#include<bits/stdc++.h>
typedef int64_t ll;
using namespace std;
ll n,l;
struct node
{
    ll cnt,pow;
}kind[35];
int f(int a)
{
    int ans=1;
    while(a>1)
    {
        ans*=2;
        a--;
    }
    return ans;
}
bool cmp(node a,node b)
{
    if(a.pow/(a.cnt*1.0)>b.pow/(b.cnt*1.0))
        return 1;
    else
        return 0;
}
ll bfs(ll left,ll cost,ll si)
{
    ll i=left/kind[si].pow;//如果能装满,尽量装
    cost+=i*kind[si].cnt;
    left-=i*kind[si].pow;
    if(left==0)//如果没有剩余容量了,递归停止,输出答案
        return cost;
    if(si==n)//如果后面没有其他种类的了,那么必须选当前种类的了,递归也要结束了
        return cost+kind[si].cnt;
    return min(cost+kind[si].cnt,bfs(left,cost,si+1));//判断一下是选当前种类值还是往后找值
}
int main()
{
    scanf("%lld%lld",&n,&l);
    for(int i=1;i<=n;i++)
    {
       scanf("%lld",&kind[i].cnt);
       kind[i].pow=f(i);    //计算容量
    }
    sort(kind+1,kind+n+1,cmp);//按照性价比排序
    printf("%lld\n",bfs(l,0,1));
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值