洛谷 P1880 石子合併 環形

2021-08-22 03:25:56 字數 1617 閱讀 3400

在乙個圓形操場的四周擺放n堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。

試設計出1個演算法,計算出將n堆石子合併成1堆的最小得分和最大得分.

輸入格式:

資料的第1行試正整數n,1≤n≤100,表示有n堆石子.第2行有n個數,分別表示每堆石子的個數.

輸出格式:

輸出共2行,第1行為最小得分,第2行為最大得分.

輸入樣例#1:

4

4 5 9 4

輸出樣例#1:

43

54

這道題目...開始本來都已經想到了利用乙個區間變數然後從間隔為1一直計算到間隔為n-1...結果還是沒有做出來...

原因是 狀態轉移方程沒寫好...我最初的寫法是dp[i][j] = max(dp[i][j-1]+sz[j],dp[i+1][j]+sum[i])...真是失敗...唉....

這道題目很容易就能想到以間隔從小到大一層一層的來計算, 但是我沒有抓好狀態變化導致狀態轉移方程錯誤

因為在間隔為k的時候有很多中情況,我可以挑選乙個間隔為1另乙個間隔為k-1 也可以挑選間隔為2另乙個間隔為k-2, 所以這些都要遍歷到, 所以在確定了區間i到j的情況下, 我們還需要從中找出和最大或者最小的那個區間,所以額外再用乙個迴圈來遍歷.

因為是環形陣列, 但是因為最大間隔為n-1,  實際並不能遍歷到n*2以外的地方, 所以可以開乙個兩倍大的陣列,用直線模擬環

另乙個點就是sum陣列, 它是乙個字首和陣列,  sum[i]表示從1到i的元素的和, 這樣要求區間i - j的和可以表示為sum[j] - sum[i-1].

最後乙個點就是在遞推遍歷的時候i要遍歷到2*n.

我之前用的是i<=n然後一直錯, 到後面頂點查錯的時候才發現, 在區間4-6區域, dp[4][6] = dp[4][4] + dp[5][6]+ sum[6]-sum[3].

其中因為點只遍歷到n, 從而dp[5][6]的值並沒有計算出來,所以導致結果錯誤.

妙啊另外還是

i hate dp

#include#include#include#includeusing namespace std;

int sum[105];//字首和

int sz[205];

int mindp[205][205],maxdp[205][205];

int n;

int main()

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

for(int j=1;j//錯誤原因 在計算4 - 6 這個區間內的結果時會遇到dp[4][4] + dp[5][6] 然而此時dp[5][6]並沒有賦值 }}

}//測試

// for(int j=1;j// cout

//int mi=0x3f3f3f3f,ma=0;

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

// cout

// cout

}

洛谷P1880 石子合併

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

洛谷 P1880 石子合併

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

洛谷 P1880 石子合併

一道區間 dp的典型題目。下面,我們先考慮不在環上,而在一條鏈上的情況。令狀態 f i,j 表示將下標在 i,j 區間的元素合併起來所能獲得的最大價值,則 f 1,n 就是問題的答案。狀態轉移式為 f i,j max quad k in i,j cost i,j,k 表示將區間 i,k 和 k 1,...