環形石子合併問題

2021-08-27 14:20:12 字數 1346 閱讀 7375

環形石子合併問題是在普通的相鄰石子合併問題的基礎上稍加拓展,石子變成了環形的,也就是說每個石子都可能和其左右兩邊的石子合併。

那麼它的dp解法也是基於普通的相鄰石子合併問題,不了解的同學可以參考我寫過的這篇文章。

有兩種解法,但他們基本的演算法思想是一樣的。

第一種是和上面鏈結文章的寫法類似,不同的是對於需要繞圈的點,普通的相鄰石子合併問題是直接跳過(因為它無法到達),而對於環形的,有兩種實現方法。

其一:使用乙個取模運算,實現環形dp。其二:將環形拓展成2倍鏈狀,開二倍的陣列即可實現,這個比較好理解好實現。

#include 

using

namespace

std;

int n, num[105], sum[105] = {};

int dp[105][105], ans = 0x3f3f3f3f;;

int main()

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

for (int k = 2; k <= n; ++k) }}

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

cout

<< ans;}/*

31 2 3

63 5 7 3 4 2

43 5 2 3

91264 324 2344 23242 435 342 3243 6787 244 // 76328

*/

第二種解法和上面不同的是dp[n][m]陣列。它的含義是:從石頭n開始的長度m的區間的dp結果。而上面的dp[n][m]陣列的含義是:從石頭n到石頭m這個閉區間的dp結果。

開這樣乙個陣列效果和第一種是一樣的,但對於我來說在思維上算是一種擴充套件。

#include 

using namespace std;

intsum[100] = , ans = 0x3f3f3f3f;

int n, num[100], dp[100][100];

int getsum(int u, int s)

int main()

for (int k = 2; k <= n; ++k) }}

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

cout << ans;}/*

31 2 3

63 5 7 3 4 2

43 5 2 3

91264 324 2344 23242 435 342 3243 6787 244 // 76328

*/

環形區間DP 環形石子合併

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

石子合併 動態規劃(環形)

1 問題描述 問題 nwpu noj 1148 在乙個圓形操場的四周擺放著n堆石子 n 100 現要將石子有次序地合併成一堆。規定每次只能選取相鄰的兩堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。編一程式,讀入石子堆數n及每堆的石子數 20 選擇一種合併石子的方案,使得做n 1次合併,...

環形石子合併(區間DP)

題目描述 將 n 堆石子繞圓形操場排放,現要將石子有序地合併成一堆。規定每次只能選相鄰的兩堆合併成新的一堆,並將新的一堆的石子數記做該次合併的得分。請編寫乙個程式,讀入堆數 n 及每堆的石子數,並進行如下計算 選擇一種合併石子的方案,使得做 n 1 次合併得分總和最大。選擇一種合併石子的方案,使得做...