題目連結:http://begin.lydsy.com/JudgeOnline/problem.php?id=1332
題意:
有n頭牛在“疊羅漢”。
第i頭牛的體重為w[i],力量為s[i]。
一頭牛的壓扁程度 = 它上面所有牛的體重之和 - s[i]
所有牛的總壓扁程度 = 所有牛中最大的那個壓扁程度
問你總壓扁程度最小為多少。
題解:
貪心。
套路:
選取最小的一個單元——相鄰的兩頭牛,進行貪心策略的區域性證明。
貪心策略:
假設最左邊為頂部,最右邊為底部。
從左往右分別編號0...n-1。
考慮兩頭相鄰的牛:交換i和i+1兩頭牛。
壓扁程度(交換之前):
i: a = sum - s[i]
i+1: b = sum + w[i] - s[i+1]
壓扁程度(交換之後):
i: a' = sum + w[i+1] - s[i]
i+1: b' = sum - s[i+1]
顯然:在交換之前,b為兩者最大值;交換之後,a'為兩者最大值。
假設未交換時為最優狀態,則交換後不可能更優。
所以有:b < a'
即:sum + w[i] - s[i+1] < sum + w[i+1] - s[i]
整理得:s[i+1] + w[i+1] > s[i] + w[i]
所以貪心策略為:w+s值越大,越放在底下。
AC Code:
1 // before: 2 // i: sum - s[i] 3 // i+1: sum + w[i] - s[i+1] 4 // after: 5 // i+1: sum - s[i+1] 6 // i: sum + w[i+1] - s[i] 7 // 8 // f1 < f4 +w[i+1] 9 // f2 > f3 -w[i] 10 // w[i] - s[i+1] < w[i+1] - s[i] 11 // w[i+1] + s[i+1] > w[i] + s[i] 12 #include <iostream> 13 #include <stdio.h> 14 #include <string.h> 15 #include <algorithm> 16 #define MAX_N 50005 17 #define INF 10000000 18 19 using namespace std; 20 21 struct Cow 22 { 23 int w; 24 int s; 25 Cow(int _w,int _s) 26 { 27 w=_w; 28 s=_s; 29 } 30 Cow(){} 31 friend bool operator < (const Cow &a,const Cow &b) 32 { 33 return a.w+a.s<b.w+b.s; 34 } 35 }; 36 37 int n; 38 Cow cow[MAX_N]; 39 40 int main() 41 { 42 cin>>n; 43 for(int i=0;i<n;i++) 44 { 45 cin>>cow[i].w>>cow[i].s; 46 } 47 sort(cow,cow+n); 48 int sum=0; 49 int ans=-INF; 50 for(int i=0;i<n;i++) 51 { 52 ans=max(ans,sum-cow[i].s); 53 sum+=cow[i].w; 54 } 55 cout<<ans<<endl; 56 }