贪心好题(两种变量的贪心)poj3262 Protecting the Flowers

来源:互联网 发布:江边城外 知乎 编辑:程序博客网 时间:2024/05/16 14:01

题意: 有N头奶牛正在吃花,FJ需要将这N头奶牛运输回去,给出每头奶牛被运输的时间(单程,不算往返)和每分钟吃花的数量,求最小的被破坏的花朵数量

题解:

这道题可不能凭感觉去贪心,因为他有两个变量,时间和数量,单纯对一种变量进行贪心无法保证答案的正确性

所以就需要分析得出贪心策略,对于这类题,一般用假设法来判断,如果只是要进行一个粗略的判断,可以这么想:

对于即将被赶走的奶牛,我们自然希望他每分钟吃花的数量越多越好,这样效率就会越高,而运输的时间越短越好

这样才能尽快回来运输下一头奶牛,于是我们就可以猜测要么是按Di/Ti贪心,要么是按Di-Ti贪心了,如果是考试,

构造几个样例试一下就可以了

下面是严谨的证明,用的是假设法:

可以推得:ans1=sigma(Ti)<1~N>*D1+sigma(Ti)<2~N>*D2+……+sigma(TI)<1~2>*Dn-1

我们假设将D1和D2交换一下位置

那么 ans2=sigma(Ti)<1~N>*D2+sigma(Ti)<1,3~N>*D1+……+sigma(Ti)<1~2>*Dn-1

如果ans1比ans2优,即:ans1<ans2

则有ans2-ans1>0 => T1*D2-T2*D1>0

同理可推得,若Di/Ti > Dj/Tj ,则先赶走第i头奶牛

代码:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cstdlib>#include<algorithm>const int MAXN=100005;using namespace std;struct node{    int T,D;    double cmp;}cow[MAXN];int N;long long sum,ans;bool cmp(node a,node b){    return a.cmp>b.cmp;}int main(){    scanf("%d",&N);    for(int i=1;i<=N;i++)    {        scanf("%d%d",&cow[i].T,&cow[i].D);        cow[i].cmp =1.0*cow[i].D/cow[i].T;    }    sort(cow+1,cow+N+1,cmp);    for(int i=1;i<=N;i++)        ans+=sum*cow[i].D,sum+=cow[i].T<<1;    printf("%I64d\n",ans);}