P1880 NOI1995 石子合併(區間dp)

2021-09-27 12:01:28 字數 1130 閱讀 3561

題目:

description:

n堆石子擺成一圈,現在要合併成一堆,每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。計算出合併的最大分和最小分。

solution: 

區間dp,分階段劃分問題。由於石子圍成了環,現在把環轉化為兩倍長的鏈。變成 (2 * n - 1) 堆,其中第 i 堆與第(i + n)  堆相同,用動態規劃求解後,取dp[1][n], dp[2][n+1] ,... ,dp[i][n+i -1] 中的最優值。

如果環是這樣:1 2 3 4 

轉化後的鏈:1 2 3 4 3 2 1 

轉化後就可以往乙個方向進行dp

區間 dp 的特點:

合併:即將兩個或多個部分進行整合,當然也可以反過來;

特徵:能將問題分解為能兩兩合併的形式;

求解:對整個問題設最優值,列舉合併點,將問題分解為左右兩個部分,最後合併兩個部分的最優值得到原問題的最優值。

code:

#includeusing namespace std;

const int inf = 0x3f3f3f3f;

int n;

int sum[300], a[300];

int dp1[300][300];//max

int dp2[300][300];//min

void init()

int main()

sum[1] = a[1];

for(int i = 1; i <= 2 * n - 1; i++) sum[i] = sum[i - 1] + a[i];

for(int len = 1; len <= n; len++) //劃分區間長度,當區間的長度為len時}}

int max = 0, min = inf;

for(int i = 1; i <= n; i++) //從不同的起點合併n堆的結果

cout << min << endl;

cout << max << endl;

return 0;

}

P1880 NOI1995 石子合併

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

P1880 NOI1995 石子合併

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

P1880 NOI1995 石子合併

這次還是給大家講解一下dp 我們則需要根據這個題目的實際含義進行變通即可.而區間dp的大致模板是 for int len 2 len n len for int i 1 i len 1 n i 那講到這裡就很自然 一點都不自然 的引入了今天我們要看的一道題,剛才我已經說了最長不下降子串行是線性dp的...