1. 程式人生 > >POJ 3253 Fence Repair (貪心)

POJ 3253 Fence Repair (貪心)

復雜度 image ace 長度 復雜 節點 clas math 個數

題意:將一塊木板切成N塊,長度分別為:a1,a2,……an,每次切割木板的開銷為當前木板的長度。求出按照要求將木板切割完畢後的最小開銷。

思路:比較奇特的貪心

每次切割都會將當前木板一分為二,可以按切割要求畫出二叉樹。

總開銷 = 各葉子節點的值 x 該葉子節點的深度

樹的深度一定,為了使總開銷盡可能的小,那麽比較深的葉子節點的值應盡可能的小,所以二叉樹應為:

技術分享

模擬出所建立的二叉樹,求出根節點的值即可

為了節省時間,可以利用優先隊列每次取出最小的兩個值合並,並將兩數之和重新加入數組,直到數組內的元素個數為一時結束,時間復雜度為O(nlogn)。

技術分享
#include<stdio.h>
#include
<queue> #include<iostream> #include<algorithm> #include<math.h> #include<string.h> #define INF 0x3f3f3f3f #define LL long long #define MOD 100000007 #define MAXSIZE 20005 using namespace std; int n,a[MAXSIZE]; LL Solve() { LL ans = 0; priority_queue<int,vector<int>,greater<int
> >Q; for(int i=1;i<=n;i++) Q.push(a[i]); while(n > 1) { int minn1 = Q.top(); Q.pop(); int minn2 = Q.top(); Q.pop(); ans += (minn1 + minn2); Q.push(minn1 + minn2); n--; } return ans; } int main() { while
(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) scanf("%d",&a[i]); LL ans = Solve(); printf("%lld\n",ans); } return 0; }
View Code

POJ 3253 Fence Repair (貪心)