環形石子合併問題是在普通的相鄰石子合併問題的基礎上稍加拓展,石子變成了環形的,也就是說每個石子都可能和其左右兩邊的石子合併。
那麼它的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 次合併得分總和最大。選擇一種合併石子的方案,使得做...