P1090 合并果子 / [USACO06NOV] Fence Repair G

~QWQ题目传送门QWQ~


 

分析:

一道水题

贪心的经典题目之一,可以使用优先队列来解决。


 

思路:

每一次合并重量最小的两堆求和即可

 

Tip:对于此策略最优性的证明:

一、本蒟蒻的证明方法:(实在是打不出数学符号,以及......很懒

1.假设一共有三堆果子,重量从小到大依次命名a、b、c

方案1:先合并a,b,得到(a+b),耗费的体力为(a+b),
再将(a+b)和c合并,得到(a+b+c),耗费的体力
为(a+b+c)。
所以此情况下耗费的总体力为(a+b+a+b+c)

方案2:先合并a,c,得到(a+c),耗费的体力为(a+c),
再将(a+c)和b合并,得到(a+b+c),耗费的体力
为(a+b+c)。
所以此情况下耗费的总体力为(a+c+a+b+c)

方案3:先合并b,c,得到(b+c),耗费的体力为(b+c),
再将(b+c)和a合并,得到(a+b+c),耗费的体力
为(a+b+c)。
所以此情况下耗费的总体力为(b+c+a+b+c)

由题设可知a<b<c;
通过做差可以进行
所以方案1优于方案2、3;
2.假设一共有四堆果子,重量从小到大依次命名a、b、c、d
可以得到许多种合并方法,根据1中给出的耗费体力多少的比较方法,
可以得出这种情况下的最优解
最优解是先将a,b进行合并,得到(a+b),耗费的体力为(a+b)
将(a+b)和c,d进行比较,将较小的两个数字合并(假设是c,d)
得到(c+d),耗费的体力为(c+d),然后将(a+b)和(c+d)进行
合并得到(a+b+c+d)耗费的总体力为(a+b+c+d+a+b+c+d)。
3假设一共有五堆果子,重量从小到大依次命名a、b、c、d
以此类推
4假设一共有六堆果子,重量从小到大依次命名a、b、c、d
以此类推

综上可得,优先合并重量和最小的两堆果子使得总体力最小。

二、大佬的证明方法:

(来自https://www.luogu.com.cn/user/49474)


 

AC代码如下:(优先队列好)

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     priority_queue<int,vector<int>,greater<int> > q;
 6     int n,x,y,z,sum=0;
 7     cin>>n;
 8     for(int i=1;i<=n;++i)
 9     {
10         cin>>x;
11         q.push(x);
12     } 
13     while(q.size()>1)
14     {
15         y=q.top();
16         q.pop();
17         z=q.top();
18         q.pop();    
19         sum+=y+z;
20         q.push(z+y);
21     }
22     cout<<sum<<endl;
23     return 0; 
24 }

 

                                                                                                                          `                                            ENDING~~~~~~

 

posted on 2020-11-28 23:01  Michael·Lee  阅读(99)  评论(0)    收藏  举报