>Link
ybtoj石子合并
luogu P1880
>解题思路
一道经典的DP(得分是累加的)
用
f
i
,
j
f_{i,j}
fi,j表示
[
i
,
j
]
[i,j]
[i,j]区间的合并最大/最小得分
然后要注意这是一个环,所以我们要破环成链进行环的处理
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000
using namespace std;
int n, a[N], fmax[N][N], fmin[N][N], maxn, minn, sum[N];
int main()
{
memset (fmin, 0x7f, sizeof (fmin));
scanf ("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf ("%d", &a[i]);
sum[i] = sum[i - 1] + a[i];
fmin[i][i] = 0;
}
for (int i = n + 1; i <= 2 * n; i++)
{
sum[i] = sum[i - 1] + a[i - n];
fmin[i][i] = 0;
}
for (int k = 2; k <= n; k++)
for (int i = 1; i <= 2 * n - k + 1; i++)
{
int j = i + k - 1;
for (int t = i; t < j; t++)
{
fmax[i][j] = max (fmax[i][j], fmax[i][t] + fmax[t + 1][j]);
fmin[i][j] = min (fmin[i][j], fmin[i][t] + fmin[t + 1][j]);
}
fmax[i][j] += sum[j] - sum[i - 1];
fmin[i][j] += sum[j] - sum[i - 1];
}
minn = fmin[0][0];
for (int i = 1; i <= n; i++)
{
minn = min (minn, fmin[i][i + n - 1]);
maxn = max (maxn, fmax[i][i + n - 1]);
}
printf ("%d\n%d", minn, maxn);
return 0;
}