BZOJ 1629 [Usaco2005 Nov]Cow Acrobats:貪心【區域性證明】

Leohh發表於2017-09-21

題目連結: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 }

 

相關文章