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) 收藏 举报
浙公网安备 33010602011771号