题目描述 Description
在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
输入描述 Input Description
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出描述 Output Description
输出共2行,第1行为最小得分,第2行为最大得分.
样例输入 Sample Input
4
4 4 5 9
样例输出 Sample Output
43
54
题解:区间DP同时跑最大值,最小值。
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define Inf 0x7fffffff
int dpx[250][250], dpn[250][250], a[250], sum[250];
int main(){
int n;
scanf( "%d", &n);
sum[0] = 0;
for ( int i = 1; i <= n; i++) scanf( "%d", &a[i]), a[n+i] = a[i];
for ( int i = 1; i <= n*2; i++) sum[i] = sum[i-1] + a[i];
for ( int f = 1; f <= n; f++)
for ( int k = 1; k < n; k++)
for ( int i = f; i < n+f-k; i++){
int L = i, R = i + k;
dpn[L][R] = Inf;
for ( int m = L; m < R; m++){
dpx[L][R] = max( dpx[L][R], dpx[L][m] + dpx[m+1][R] + sum[R] - sum[L-1] );
dpn[L][R] = min( dpn[L][R], dpn[L][m] + dpn[m+1][R] + sum[R] - sum[L-1] );
}
}
int ax = 0, an = Inf;
for ( int i = 1; i <= n; i++ ){
ax = max( ax, dpx[i][i+n-1]);
an = min( an, dpn[i][i+n-1]);
}
printf( "%d\n%d", an, ax);
}