题意:有n堆石子,相邻石子堆可以合并为一堆,合并分数等于合并之后石子堆大小,求所有石子合并为一堆后最大得分和最小得分
思路:取dp[i][j]为区间[i, j]内合并石子最小分数,则dp[i][j] = min(dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]),i≤k<j,类似分治递增区间间隔,表示每次只取相邻的两堆合并,注意序列为环,需要考虑环的问题
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
const int maxn = 1e3+5;
const int inf = 0x3f3f3f3f;
int n, a[maxn], sum[maxn], dp[maxn][maxn], dp2[maxn][maxn];
int main()
{
// freopen("test.txt", "r", stdin);
while (cin >> n) {
sum[0] = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum[i] = sum[i-1] + a[i];
}
for (int i = n+1; i <= 2*n; i++) {
a[i] = a[i-n];
sum[i] = sum[i-1] + a[i];
}
for (int p = 1; p < n; p++) {
for (int i = 1, j = i + p; i<n+n && j<n+n; i++, j = i+p) {
dp[i][j] = inf;
for (int k = i; k < j; k++) {
dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
dp2[i][j] = max(dp2[i][j], dp2[i][k]+dp2[k+1][j]+sum[j]-sum[i-1]);
}
}
}
int minn = inf, maxx = 0;
for (int i = 1; i <= n; i++) {
minn = min(minn, dp[i][i+n-1]);
maxx = max(maxx, dp2[i][i+n-1]);
}
cout << minn << endl;
cout << maxx << endl;
}
return 0;
}