题意: 有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);
}