POJ 3262 Protecting the Flowers

贪心好题~~~

方法如下:

当前最优,因为每一次搬运之后剩下的问题和原问题一样,只是规模变小了,故如果每次选出当前最优的解来进行选取,则累计起来的解也是最优的.
所以这是一道贪心题.
选择策略,
1 在二个中间选择之中,能根据time/eat小的那个为最优解
证明:
二个羊中 A,B,属性分别为分别为eatA,timeA,eatB,timeB
选A的时候损失timeA*eatB
选B的时候损失timeB*eatA
双方同除以eatA*eatB.
令time/eat为一个羊的比率x
可以证明x小的那个为最优解.

定理,如果有一个选择在n个选择中是最优的,那么(在包含这个选择的)n-1个选择中也是最优的,

逆否命题,如果一个选择在n-1个选择中不是最优的,那么在n个选择中也不是最优的.

推论,如果一个选择在2个选择中不是最优的,那么在n个选择中也不是最优的

所以将羊按照比率x排序,可以找到一个羊A在与其它所有羊比较的过程中都是最优的,

或者说其它n-1的羊在与别的羊做两个之间选一个的选择的时候不是最优的,所有这n-1个羊不是最优解的.
所以羊A是n头羊中最优解

(这个证明先令x的值都是不同的,对x相同的证明只需要将最优,改成没有更优即可 ^_^ )


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 100010;

struct Node
{
    int t, c;
    Node() {}
    Node(int t_t, int t_c) : t(t_t), c(t_c) {}
    bool operator < (const Node &p) const
    {
        return p.c * t < c * p.t;
    }
}p[MAXN];
int N;
long long sum;

int main()
{
    //freopen("aa.in", "r", stdin);
    //freopen("bb.out", "w", stdout);

    while(scanf("%d", &N) != EOF)
    {
        sum = 0;
        for(int i = 0; i < N; ++i)
        {
            scanf("%d %d", &p[i].t, &p[i].c);
            p[i].t *= 2;
            sum += p[i].c;
        }
        sort(p, p + N);
        long long ans = 0;
        for(int i = 0; i < N; ++i)
        {
            //cout << p[i].t << " " << p[i].c << endl;
            sum -= p[i].c;
            //cout << sum * p[i].t << endl;
            ans += sum * p[i].t;
        }
        cout << ans << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值