1. 程式人生 > 實用技巧 >P1090 合併果子 / [USACO06NOV] Fence Repair G

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~~~~~~