最小代價樹

2021-06-05 22:38:42 字數 1014 閱讀 5095

題目:

描述以下方法稱為最小代價的字母樹:給定一正整數序列,例如:4,1,2,3,在不改變量的位置的條件下把它們相加,並且用括號來標記每一次加法所得到的和。

例如:((4+1)+ (2+3))=((5)+(5))=10。除去原數不4,1,2,3之外,其餘都為中間結果,如5,5,10,將中間結果相加,得到:5+5+10=20,那麼數20稱為此數列的乙個代價,若得到另一種演算法:(4+((1+2)+3))=(4+((3)+3))=(4+(6))=10,數列的另乙個代價為:3+6+10=19。若給出n個數,可加n-1對括號,求出此數列的最小代價。

注:結果範圍不超出longint.

輸入第一行為數n(1≤n≤200),第二行為n個正整數,整數之間用空格隔開。

輸出輸出僅一行,即為最少代價值。

樣例輸入

44  1  2  3

樣例輸出19

分析:該題類似石子合併問題:

在一條直線上擺著n堆石子,現要將石子有序的合併成一堆,規定如下:每次只能移動相鄰的2堆石子合併,合併花費為將的一堆石子的數量。設計乙個演算法,將這n堆石子合併成一堆的總花費最小(或最大)。

如果熟悉矩陣連乘對這類問題肯定非常了解。矩陣連乘每次也是合併相鄰兩個矩陣(只是計算方式不同)。那麼石子合併問題可用矩陣連乘的方法來解決。

那麼最優子結構是什麼呢?如果有n堆,第一次操作肯定是從n-1個對中選取一對進行合併,第二次從n-2對中選取一對進行合併,以此類推……

設f[i][j]表示i-j合併的最優值, sum[i][j]表示第i堆石子到第j堆石子的總數量,遞推公式如下:

(矩陣連乘可見《演算法導論》,講的很詳細)

下面給出**:

#include #include int n,arr[210],sum[210][210],m[210][210];

void calsum();

void calminsum();

int main()

{ int i;

scanf("%d",&n); //輸入元素個數

for (i=0;i

最小(代價)生成樹

從圖中任意取出乙個頂點,把他當作一棵樹,然後從這棵樹相接的邊中選取一條最短 權值最小 的邊,並將這條邊及其所連線的頂點也併入這棵樹中,此時得到一顆有兩個頂點的樹。然後在這棵樹中相連的頂點中選取最短的邊,並將圖中的所有頂點併入樹中為止,此時得到的樹就是最小生成樹。流程如圖 普利姆演算法 void pr...

最小代價樹(動態規劃)

description 以下方法稱為最小代價的字母樹 給定一正整數序列,例如 4,1,2,3,在不改變量的位置的條件下把它們相加,並且用括號來標記每一次加法所得到的和。例如 4 1 2 3 5 5 10。除去原數不4,1,2,3之外,其餘都為中間結果,如5,5,10,將中間結果相加,得到 5 5 1...

最小代價生成樹 Kruskal演算法

1.圖的儲存結構 採用邊集陣列儲存圖。2.定義parent i 陣列,輔助完成連通分量的處理。陣列分量的值表示頂點i的雙親結點 初值為 1 當一條邊 u,v 的兩個頂點的根結點不同時,這兩個結點屬於不同的連通分量 利用parent陣列查詢一棵樹的根節點。當乙個結點n的parent 1,樹的根節點即為...