传送门 将 n 堆石子绕圆形操场排放,现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数记做该次合并的得分。
请编写一个程序,读入堆数 n 及每堆的石子数,并进行如下计算:
选择一种合并石子的方案,使得做 n−1 次合并得分总和最大。
选择一种合并石子的方案,使得做 n−1 次合并得分总和最小。
输入格式
输入第一行一个整数 n,表示有 n 堆石子。
第二行 n 个整数,表示每堆石子的数量。
输出格式
输出共两行:
第一行为合并得分总和最小值,
第二行为合并得分总和最大值。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int a[210];
int dpmax[210][210];
int dpmin[210][210];
int sum[210];
const int inf = 0x3f3f3f3f;
int main()
{
int n;
cin>>n;
for(int i = 1; i <= n; i++)
{
cin>>a[i];
a[i+n] = a[i];
}
for(int i = 1; i <= 2*n; i++)
{
sum[i] = sum[i-1] + a[i];
}
int ansmin = inf,ansmax = 0;
for(int len = 2; len <= n; len++)
{
for(int l = 1; l+len-1 <= n*2; l++)
{
int r = l+len-1;
dpmin[l][r] = inf;
dpmax[l][r] = -inf;
for(int k = l; k < r; k++)
{
dpmin[l][r] = min(dpmin[l][r],dpmin[l][k] + dpmin[k+1][r]+sum[r]-sum[l-1]);
dpmax[l][r] = max(dpmax[l][r], dpmax[l][k]+dpmax[k+1][r]+sum[r]-sum[l-1]);
}
}
}
for(int i = 1; i <= n; i++)
{
ansmin = min(ansmin,dpmin[i][i+n-1]);
ansmax = max(ansmax,dpmax[i][i+n-1]);
}
printf("%d\n%d\n",ansmin,ansmax);
}