Description
Farmer John went to cut some wood and left N (2 ≤ N ≤ 100,000) cows eating the grass, as usual. When he returned, he found to his horror that the cluster of cows was in his garden eating his beautiful flowers. Wanting to minimize the subsequent damage, FJ decided to take immediate action and transport each cow back to its own barn.
Each cow i is at a location that is Ti minutes (1 ≤ Ti ≤ 2,000,000) away from its own barn. Furthermore, while waiting for transport, she destroys Di (1 ≤ Di ≤ 100) flowers per minute. No matter how hard he tries, FJ can only transport one cow at a time back to her barn. Moving cow i to its barn requires 2 × Ti minutes (Ti to get there and Ti to return). FJ starts at the flower patch, transports the cow to its barn, and then walks back to the flowers, taking no extra time to get to the next cow that needs transport.
Write a program to determine the order in which FJ should pick up the cows so that the total number of flowers destroyed is minimized.
Input
Lines 2.. N+1: Each line contains two space-separated integers, Ti and Di, that describe a single cow's characteristics
Output
Sample Input
6 3 1 2 5 2 3 3 2 4 1 1 6
Sample Output
86
题意:
有n个牛在FJ的花园乱吃花朵,所以FJ要赶他们回牛棚。每个牛在被赶走之前每分钟吃Di个花朵。赶它回去FJ要花的时间是Ti。在被赶走的过程中牛就不能乱吃了。
贪心。T/D越小就应该越早赶回去,证明如下:
假设序列都由二元组组成,二元组是由T和D组成,那么对一个序列有相邻的两头牛是这样的
..........(T1, D1) , (T2, D2)....................
如果(T1 , D1)和(T2 , D2)交换位置了
变成新序列
..........(T2 , D2) , (T1 , D1 ).....................
假设在这之前FJ已经花了x时间了。
那么赶完这两头牛的损失的量就分别为
x*D1 + (x + 2*T1 ) * D2
x*D2 +(x + 2*T2 ) * D1
二者做差
得到 T1D2 - D1T2
若 T1D2 < D1T2 ,则有第一个序列优于第二个
即 T1/D1 < T2/D2 ;
那么对于任意的序列,我们都可以通过若干次这种相邻的交换使得序列变成最优的。
证明完毕。
刚开始自己想利用函数解析式分析出满足什么样条件的牛应该越早被赶回去,结果没分析出来。看了别人的才知道,可以将两种相反的决策相比较,比如做差,然后再从中分析。
#include "cstdio"
#include "algorithm"
using namespace std;
struct node
{
int T,D;
}cow[1000005];
long long s[1000005];
bool cmp(node x,node y)
{
return x.T*1.0/x.D < y.T*1.0/y.D;
}
int main(int argc, char const *argv[])
{
int N;
while(~scanf("%d",&N))
{
for(int i = 0;i < N;i++)
scanf("%d%d",&cow[i].T,&cow[i].D);
sort(cow,cow+N,cmp);
long long ans = 0;
for(int i = N-1;i > 0;i--)
{
ans += cow[i].D;
s[i-1] = ans;
}
s[N-1] = 0;
ans = 0;
for(int i = 0;i < N;i++)
{
ans += s[i]*cow[i].T*2;
}
printf("%lld\n",ans);
}
return 0;
}