石子合併問題

2021-07-31 15:09:50 字數 2569 閱讀 7717

石子合併問題是最經典的dp問題。首先它有如下3種題型:

(1)有n堆石子,現要將石子有序的合併成一堆,規定如下:每次只能移動任意的2堆石子合併,合併花費為新合成的一堆石子的數量。求將這n堆石子合併成一堆的總花費最小(或最大)。

分析:當然這種情況是最簡單的情況,合併的是任意兩堆,直接貪心即可,每次選擇最小的兩堆合併。本問題實際上就是哈夫曼的變形。

(2)有n堆石子,現要將石子有序的合併成一堆,規定如下:每次只能移動相鄰的2堆石子合併,合併花費為新合成的一堆石子的數量。求將這n堆石子合併成一堆的總花費最小(或最大)。

分析:我們熟悉矩陣連乘,知道矩陣連乘也是每次合併相鄰的兩個矩陣,那麼石子合併可以用矩陣連乘的方式來解決。

設dp[i][j]表示第i到第j堆石子合併的最優值,sum[i][j]表示第i到第j堆石子的總數量。那麼就有狀態轉移公式:

直線取石子問題的平行四邊形優化:

[cpp]view plain

copy

#include 

#include 

#include 

using

namespace

std;  

const

intinf = 1 <

const

intn = 1005;  

intdp[n][n];  

intp[n][n];  

intsum[n];  

intn;  

intgetminval()  

for(int

len=1; len

}  dp[i][end] = tmp;  

p[i][end] = k;  

}  }  

return

dp[1][n];  

}  int

main()  

printf("%d\n"

,getminval());  

}  return

0;  

}  

(3)問題(2)的是在石子排列是直線情況下的解法,如果把石子改為環形排列,又怎麼做呢?

分析:狀態轉移方程為:

其中有:

可以看出,上面的(2)(3)問題的時間複雜度都是o(n^3),由於過程滿足平行四邊形法則,故可以進一步優化到o(n^2)。

原處:

石子合併問題

在乙個圓形操場的四周擺放著n堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。試設計乙個演算法,計算出將n堆石子合併成一堆的最小得分和最大得分。分析 假設有n堆石子需要合併,可以設計乙個2 n 1個元素的陣列來儲存每堆石子的個數。...

石子合併問題

在乙個圓形操場的四周擺放著n堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。試設計乙個演算法,計算出將n堆石子合併成一堆的最小得分和最大得分。沒有用dp 感覺一般的也能寫,時間複雜度也不高。include include inc...

石子合併問題

石子合併問題是最經典的dp問題。首先它有如下3種題型 1 有n堆石子,現要將石子有序的合併成一堆,規定如下 每次只能移動任意的2堆石子合併,合併花費為新合成的一堆石子的數量。求將這n堆石子合併成一堆的總花費最小 或最大 分析 當然這種情況是最簡單的情況,合併的是任意兩堆,直接貪心即可,每次選擇最小的...