洛谷 P1880 NOI1995 石子合併

2021-08-28 02:41:40 字數 1420 閱讀 1226

在乙個圓形操場的四周擺放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

解法:區間合併

區間合併的模版經典題(然而我是第一次做)

令dp[i][j]表示將i-j內的所有石子合併成一堆後的最值

那麼顯然我們可以將這個區間劃分為兩部分,可以由這兩部分組合而來。

dp[i][j] = dp[i][k] + dp[k + 1][j] + sum(i, j) 

得到狀態轉移方程以後我們就要開始考慮怎麼寫了。

顯然在計算長度較大的區間時長度較小的區間已經被計算出來了。

所以我們考慮列舉長度,再列舉起始位置即可。

那麼計算一段區間的和我們可以直接用字首和。

還有乙個問題由於這一堆石子是乙個環而不是一條鏈,所以我們將原序列擴充一遍,最後列舉各位置長度為n區間取到最值即可。

#include #include #include #include #include #include #include #include #define pii pair#define vi vector#define ll long long

#define eps 1e-3

using namespace std;

const int maxn = 1e3 + 10;

ll dpmn[maxn][maxn];//dp[i][j]表示將第i到j堆石子合併能產生的最大值

ll dpmx[maxn][maxn];//dp[i][j]表示將第i到j堆石子合併能產生的最小值

int a[maxn];

ll sum[maxn];

int main()

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

n *= 2;

for (int len = 2; len <= n / 2; len++)}}

ll mn = int_max, mx = int_min;

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

cout << mn << '\n' << mx << endl;

return 0;

}

洛谷 P1880 NOI1995 石子合併

這道題是之前石子合併的加強板 不同在於是乙個環 處理方法就是把陣列 乘以2,列舉起點轉化成鏈。以後這種環的問題應該都可以這樣來轉化。陣列空間不要忘了乘以2 然後要注意區間從長度為2開始,初始化為最大或最小 注意這裡的得分是合併之後的得分,所以單獨一堆是沒有得分的。include include in...

洛谷 P1880 NOI1995 石子合併

鏈結 思路 區間dp,只不過是環上的,把整個序列複製乙份就好了。dp l r 表示l到r的最大 小值,狀態轉移方程就是dp l r max min 5455 inta m 56int sum m 57int dp max 1005 1005 58 int dp min 1005 1005 59 in...

洛谷P1880 NOI1995 石子合併 題解

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