NOIP模拟赛 护花

【题目描述】

约翰留下他的N(N<=100000)只奶牛上山采木.他离开的时候,她们像往常一样悠闲地在草场里吃草.可是,当他回来的时候,他看到了一幕惨剧:牛们正躲在他的花园里,啃食着他心爱的美丽花朵!为了使接下来花朵的损失最小,约翰赶紧采取行动,把牛们送回牛棚. 牛们从1到N编号.第i只牛所在的位置距离牛棚Ti(1≤Ti≤2000000)分钟的路程,而在约翰开始送她回牛棚之前,她每分钟会啃食Di(1≤Di≤100)朵鲜花.无论多么努力,约翰一次只能送一只牛回棚.而运送第第i只牛事实上需要2Ti分钟,因为来回都需要时间.    写一个程序来决定约翰运送奶牛的顺序,使最终被吞食的花朵数量最小.

【输入格式】

第1行输入N,之后N行每行输入两个整数Ti和Di

【输出格式】

一个整数,表示最小数量的花朵被吞食

【样例输入】

6

3 1

2 5

2 3

3 2

4 1

1 6

【样例输出】

86

【样例解释】

 约翰用6,2,3,4,1,5的顺序来运送他的奶牛 

贪心,类似于国王游戏,只不过国王游戏需要高精度(还不去填坑

设S=∑(Di)

ans=min{2T[i]*(S-D[i]),2T[j]*(S-D[j])}

设2T[i]*(S-D[i])<2T[j]*(S-D[j])

可得T[i]/T[j]<(S-D[j])/(S-D[i])

显然

T[i]<T[j]且D[j]<D[i]时成立

两式相乘T[i]*D[j]<T[j]*D[i]

证毕

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 
 5 struct data
 6 {
 7     int t,d;
 8 }q[100001];
 9 long long n,sum=0,ans=0;
10 
11 bool cmp(data a,data b)
12 {
13     return a.t*b.d<b.t*a.d;
14 }
15 
16 int main()
17 {
18     cin>>n;
19     for(int i=1;i<=n;i++)
20     {
21         cin>>q[i].t>>q[i].d;
22         sum+=q[i].d;
23     }
24     sort(q+1,q+n+1,cmp);
25     for(int i=1;i<=n;i++)
26     {
27         sum-=q[i].d;
28         ans+=2*q[i].t*sum;
29     }
30     cout<<ans<<endl;
31     return 0;
32 }
原文地址:https://www.cnblogs.com/InWILL/p/6001893.html