Poj百练 4110:圣诞老人的礼物-Santa Clau’s Gifts (分类:贪心)

解法:
按礼物的价值/重量比从大到小依次选取礼物,对选
取的礼物尽可能多地装,直到达到总重量w
复杂度: O(nlogn)

#include<cstdio>
#include<algorithm>
using namespace std;

int n,m;
struct s
{
    int a;
    int b;
    double x;
};
struct rule
{
    bool operator ()(const s & s1,const s & s2)
    {
        return s1.x > s2.x;
    }
};
int main()
{
    scanf("%d%d",&n,&m);
    s h[10000];
    for( int i=0; i<n; i++)
    {
        scanf("%d%d",&h[i].a,&h[i].b);
        h[i].x=h[i].a/h[i].b;
    }
    sort(h,h+n,rule());

    double num=0,mum=0;
    for(int i=0; i<n; i++)
    {
        if(m-mum>=h[i].b)
        {
            num+=h[i].a;
            mum+=h[i].b;
        }
        else
            {num+=(m-mum)*h[i].x;
            break;
            }
    }
    printf("%.1lf",num);
    return 0;
}

下面是一种比较好的写法:

#include<cstdio>
#include<algorithm>
using namespace std;
const double eps = 1e-6;
struct Candy
{
    int v;
    int w;
    bool operator < (const Candy & c)
    {
        return	double(v)/w - double(c.v)/c.w > eps;
    }
} candies[110];
int main()
{
    int n,w;
    scanf("%d%d",&n,&w);
    for(int i = 0; i < n; ++i)
        scanf("%d%d", &candies[i].v, &candies[i].w);

    sort (candies,candies+n);
    int totalW = 0;
    double totalV = 0;
    for(int i = 0; i < n; ++i)
    {
        if( totalW + candies[i].w <= w)
        {
            totalW += candies[i].w;
            totalV += candies[i].v;

        }
        else
        {



            totalV += candies[i].v *
                      double(w-totalW)/candies[i].w;

            break;
        }
    }
    printf("%.1f",totalV);
    return 0;
}

最后贪心重在证明

证明: 替换法。对于用非此法选取的最大价值糖果箱序列, 可以将其按价值/重量比从大到小排序后得到: 序列1:a1, a2 …
用序列1和按上述解法选取的序列2依次进行比较: 序列2:b1, b2 …
价值/重量比相同的若干箱糖果,可以合并成一箱,所以两个序列中元素都不重复 对于发现的第一个 ai != bi ,则必有:ai< bi
则在序列1中,用 bi 这种糖果,替代若干重量的 ai 这种糖果,则会使得序列1的总价 值增加,这和序列1是价值最大的取法矛盾

所以:序列1 = 序列2 (序列2不可能是序列1的一个前缀且比序列1短)
每一步行动总是按某种指标选取最优的操作来进行, 该指标只看眼前,并不考虑以后可能造成的影响。
贪心算法需要证明其正确性。 “圣诞老人礼物”题,若糖果只能整箱拿,则贪心法错误。

每一步行动总是按某种指标选取最优的操作来进行, 该指标只看眼前,并不考虑以后可能造成的影响。
贪心算法需要证明其正确性。

“圣诞老人礼物”题,若糖果只能整箱拿,则贪心法错误。
考虑下面例子:
3个箱子(8,6) (5,5) (5,5),雪橇总容量10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值