木板切割問題 貪心

2022-05-02 11:39:08 字數 1022 閱讀 6636

一、問題引入

農夫約翰為了修理柵欄,要將一塊很長的木塊切成n塊。準備切成的長度分別是l1、l2、、、,ln,未切割前的木板長度切好為切割後木板長度的總和。每次切斷木板時的開銷是這塊木板的長度。(1 ≤ n ≤ 20000,0 ≤ li ≤ 50000)

二、解題思路

由於n的值非常大,不可能列舉所有情況再求解,必須用一種比較高效的演算法。木板的切割循序不確定,看似自由度很高,是先選擇切出較短的,還是切較長的。如果我們把一種完全切割後的情況列舉出來,會發現可以用貪心演算法

驚奇的發現,這種切法的切割費用之和 == 所有非葉子節點權值和 == 葉子節點的權值 * 深度(根節點深度為0)

即 33 = 15 + 7 + 8 + 3 = 3*2 + 4*2 + 5*2 + 1*3 + 2*3

問題轉化為,已知所有的葉子節點和根節點,求葉子節點的權值 * 深度和的最小值。

顯然,使權值大的深度小,權值小的深度大。於是,此時的最佳切割方法應該具有如下性質:

最短版和次短板應該是兄弟節點

這一性質在切割過程中始終成立,反過來,我們可以根據這種性質建立起對應的二叉樹。即每次合併最小的,合併後的值加到總費用中。(注意建立的樹不唯一,但每種的結果一樣,所以選其中一種就行)

由於是每次取最小和次小合併,維護乙個優先佇列就行

三、**實現

1 #include2 #include3 #include4

using

namespace

std;

56 typedef long

long

ll;7

const

int maxn = 20000 + 10;8

intn, l[maxn];910

void

slove()

1130 printf("

%lld\n

", ans);31}

3233

intmain()

3441

return0;

42 }

四、總結

NOIP模擬 切割木板

小 z 是個特別墮落的小朋友,上數學課的時候經常有奇奇怪怪的想法。小 z 的的包裡有塊 n m 的長方形木板,小 z 想把木板全部切成 1 1 的小正方形 用來玩拼圖 但木板本身並不均勻,因此從不同的線切割下去要花不同的代價。而且對於一塊木板,切割一次以後就被分割成兩塊,而且由於不能把這兩塊木板拼在...

NOIP模擬 切木板(貪心)

有乙個 m n 的矩形木板。你需要把這個木板切成 1 1 的小方塊,也就是豎著切 n 1 刀 橫著切 m 1 刀。橫著切第 i 個位置的權值為 xi 豎著切第 j 個位置的權值為 yj 切某一刀時的費用為切這一刀的權值乘上切過的塊數。請你安排切的順序使得所有費用之和最小。第一行兩個數 m,n 接下來...

NOIP模擬 切木板(貪心)

有乙個 m n 的矩形木板。你需要把這個木板切成 1 1 的小方塊,也就是豎著切 n 1 刀 橫著切 m 1 刀。橫著切第 i 個位置的權值為 xi 豎著切第 j 個位置的權值為 yj 切某一刀時的費用為切這一刀的權值乘上切過的塊數。請你安排切的順序使得所有費用之和最小。第一行兩個數 m,n 接下來...