1. 程式人生 > >Fence Repair POJ - 3253

Fence Repair POJ - 3253

題解 eno 結合 arm ont cst 葉子節點 and int

(英文不好的同學可以參考白書)

Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each having some integer length Li (1 ≤ Li ≤ 50,000) units. He then purchases a single long board just long enough to saw into the N planks (i.e., whose length is the sum of the lengths Li

). FJ is ignoring the "kerf", the extra length lost to sawdust when a sawcut is made; you should ignore it, too.

FJ sadly realizes that he doesn‘t own a saw with which to cut the wood, so he mosies over to Farmer Don‘s Farm with this long board and politely asks if he may borrow a saw.

Farmer Don, a closet capitalist, doesn‘t lend FJ a saw but instead offers to charge Farmer John for each of the N

-1 cuts in the plank. The charge to cut a piece of wood is exactly equal to its length. Cutting a plank of length 21 costs 21 cents.

Farmer Don then lets Farmer John decide the order and locations to cut the plank. Help Farmer John determine the minimum amount of money he can spend to create the N planks. FJ knows that he can cut the board in various different orders which will result in different charges since the resulting intermediate planks are of different lengths.

Input Line 1: One integer N, the number of planks
Lines 2.. N+1: Each line contains a single integer describing the length of a needed plank Output Line 1: One integer: the minimum amount of money he must spend to make N-1 cuts Sample Input
3
8
5
8
Sample Output
34
Hint He wants to cut a board of length 21 into pieces of lengths 8, 5, and 8.
The original board measures 8+5+8=21. The first cut will cost 21, and should be used to cut the board into pieces measuring 13 and 8. The second cut will cost 13, and should be used to cut the 13 into 8 and 5. This would cost 21+13=34. If the 21 was cut into 16 and 5 instead, the second cut would cost 16 for a total of 37 (which is more than 34). 題解:   這個題目來自於白書,而且題解也很詳細,但為了方便沒有白書的同學,這裏還是講一下。   首先,我們可以思考將一個大區間不斷地切成兩瓣,直到切到我們想要的節點為止,可以得到一棵類似與線段樹的二差樹,然後每個葉子節點就是題目所給的區間,這個可以自己在腦中想一下。   然後,我們考慮,對於每個葉子節點,他的花費就是 長度*深度。因為深度就是切割的次數,然後可以用葉子節點拼湊出大的區間,乘法結合率一下就證明了,那麽肯定長度最小的的節點放在深度最大的地方,因為他是一棵二差樹,所以次小的區間也放在深度最大的地方,這樣一定是最優的,然後考慮將他們和起來,得到劃分前的區間形態,然後又是一樣的方法找最小次小,知道區間個數為1。   用堆維護就一下就好了。 代碼:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
#define MAXN 200000
#define ll long long
using namespace std;
int n,tot=0;
ll ans=0;
priority_queue<int> q;

bool cmp(int x,int y){
    return x>y;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int x;scanf("%d",&x);
        q.push(-x);
    }
    while(q.size()!=1){
        int f=q.top();q.pop();
        int s=q.top();q.pop();
        q.push(s+f);
        ans+=-s-f;
    }
    printf("%lld\n",ans);
    return 0;
}

Fence Repair POJ - 3253