題目的意思是。要把一塊木板切成所需要的n塊,但是每切一刀需要收費。收費的方法是(網上有一些人理解有誤):
每當在一塊木板上動刀子,這塊木板的原有長度代表了這刀的費用。
思路:切割的過程可以用一棵二叉樹表示,每個節點有兩個或者沒有子節點,
節點儲存切割過程中每塊木板的長度。父節點的值=兩個子節點相加
根節點是原始木板長度。每塊所需要的木板都是葉子節點。
非葉子節點的值之和就是要花的總**。
定理1:
如果要使得總**最少,就要求高層(靠近根)的每乙個節點的值 大於 低層每乙個節點的值
證明:
運用反證法,假如某一棵二叉樹,總**最低,且不滿足定理1。
假如第n層a節點大於第m層b節點,n>m a-b = c
那麼,我們可以構造出一棵二叉樹,即把第n層的a節點和m層的b節點交換(如果是非葉子節點,交換子樹),之後保證 父節點的值=兩個子節點相加 。
a值的減少c會使得自己的每個先輩節點減少c, b值增加c也會使自己每個先輩節點增加c。由於a在b的下層,導致a的先輩比b的先輩多,
每個先輩節點必定不是葉子節點,這就使得總**降低,和原二叉樹總價最低矛盾。
定理2:
每一顆二叉樹,只要高層(靠近根)的每乙個節點的值 大於 低層每乙個節點的值,那麼這些二叉樹所代表的總價值相同。
證明:原理同定理1,通過同一層的節點(或者子樹)相互交換,構造出的任意一棵滿足要求的二叉樹,
由於先輩節點值增加,減少的值相互抵消,所以總價值不變。
由於哈弗曼樹滿足我們所需要的二叉樹的性質(這也同時說明,滿足總費用最少的二叉樹不一定是哈夫曼樹),所以這道題用哈夫曼樹來解。
int find_small(int arr, int len, int &a, int &b)
cnt = n;
int w=0;
if(cnt==1)
while(cnt!=1)
cout<
poj 3253 哈夫曼思想 優先佇列實現
這兩天都沒怎麼寫 因為數學拉的太多了。期中考來了。今天看了一篇文章,又想起這題,就跑來看看,發現之前居然並沒有寫題解。思路,每個木板的開銷應該是木板的長度乘以節點的深度。那麼就是最短的板應該是深度最大的節點之一,每次將最短的和次短的合併起來就是當前最小的開銷,一直加起來直到所有木板最後合併成乙個木板...
poj3253 貪心選擇
por3242 fence repair 題目大意 給定乙個木條,鋸成指定要求的長度,每鋸一次花費是被鋸成的兩段長度之和。求最小的花費。解題思路 將小木條合併成乙個大木條,貪心。每次都選取最小的長度合併。求最小的時候用優先佇列。include include include include prag...
poj3253 優先佇列
解題思路 分析得非常好!利用huffman思想,要使總費用最小,那麼每次只選取最小長度的兩塊木板相加,再把這些 和 累加到總費用中即可 本題雖然利用了huffman思想,但是直接用huffmantree做會超時,可以用優先佇列做 因為樸素的huffmantree思想是 1 先把輸入的所有元素公升序排...