dp 石子合併問題

2021-07-08 13:23:54 字數 1756 閱讀 1118

石子合併問題:

有n(n<100)堆石子,價值分別為a0,a1......a(n-1),每次將其中的相鄰的兩堆合併,合併的代價為兩堆石子的價值和,合併後用合併之後的一堆石子代替之前的兩堆石子,價值為原來

兩堆價值之和,求最終將所有的石子合併成一堆之後的代價最小值。

問題一:n堆石子排成一條直線

這個問題比較簡單,類似與矩陣連乘的問題。

dp[n][m] 為合併n和m之間的石子的代價

則有dp[i][j] = 0 , i==j

dp[n][m] = min(dp[n][k]+dp[k+1][m]) + sum(n,m)  n<=k

#include #include #include #include #include #include using namespace std;

const int inf = 1<<20 ;

const int maxn = 105 ;

int sum[maxn];

int dp[maxn][maxn];

int n,a[maxn];

int main()

for(int i = 0 ; i < n ; i++)

for(int v = 1 ; v < n ; v++)}}

printf("%d\n",dp[0][n-1]);

}return 0;

}

//直線取石子的平行四邊形的優化

#include #include #include using namespace std;

const int inf = 1 << 30;

const int n = 1005;

int dp[n][n];

int p[n][n];

int sum[n];

int n;

int getminval()

for(int len=1; len問題二:n堆石子圍成一圈

如果石子是排成圓形,其餘條件不變,那麼最優值又是什麼呢?

因為圓形是首尾相接的,初一想,似乎與直線排列完全成了兩個不同的問題。因為每次合併後我們都要考慮最後乙個與第乙個的合併關係。直線版的矩陣連乘對角線式的最優子結構不見了。f(i, j)表示i-j合併的最優值似乎並不可行,因為我們可以得到的最優值第一步就是第乙個與最後乙個合併,那麼f(i, j)並不能表示這種關係。

修改一下,f(i, j)表示從第i個開始,合併後面j個得到的最優值。sum(i, j)表示從第i個開始直到i+j個的數量和。那麼這個問題就得到解決了。注意要把其看成環形,即在有限域內的合併。

破圓化直:將圓形的石子歸併化為直線型石子歸併。

方法是:將原來的石子長度增加一倍,加在原來的後面,a[1]~a[n],a[1]~a[n],

求從1,2,3,~n開始的n個合併的最小值,最其中乙個最小值即可。

#include #include #include using namespace std;

const int inf = 1 << 30;

const int n = 205;

int mins[n][n];

int maxs[n][n];

int sum[n],a[n];

int minval,maxval;

int n;

int getsum(int i,int j)

void work(int a,int n)

{ for(int i=0;i

dp 石子合併問題

問題描述 在乙個圓形操場的四周擺放著n 堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰 的2 堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。程式設計任務 試設計乙個演算法,計算出將n堆石子合併成一堆的最小得分和最大得分。資料輸入 包含兩行,第1 行是正整數n 1 n 100 ...

石子合併問題(區間DP)

有n堆石子,要合併成一堆,規則是只能和相鄰的合併,每次合併的代價是合併出的石子堆的石子數量,求最小花費。in 4 4 4 5 9 out 43 直接貪心只能取到區域性的最佳結果。方程是很明顯的,dp i j min dp i j dp i k dp k 1 j sum j sum i s i dp陣...

dp演算法 石子合併問題

這兩天看了一下這個問題,原題是這樣的 有n堆石子,現要將石子有序的合併成一堆,規定如下 每次只能移動相鄰的2堆石子合併,合併花費為新合成的一堆石子的數量。求將這n堆石子合併成一堆的總花費最小 或最大 這個題目在第一次剛看的時候,一臉懵逼,題目看懂了,但是怎麼去求花費怎麼都沒有想明白,後來在網上看了一...