You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

56 lines
2.0 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 410; // 注意开双倍空间
int a[N]; // 原始数组
int s[N]; // 前缀和
int f[N][N]; // 最小得分,从i堆合并到j堆的最小代价
int g[N][N]; // 最大得分,从i堆合并到j堆的最大代价
int n, m;
// 搜索出l~r的最小得分
int dfs1(int l, int r) { // 求出最小得分
int &v = f[l][r]; // 利用C++特性定义一个v,简化代码
if (l == r) return v = 0; // l==r时返回0
if (v) return v; // 已保存的状态不必搜索
int res = INF; // 初始值赋为最大值以求最小值
// 枚举l~r之间的每个可能k,之所以k∈[l,r),可以看下面的递推关系式dfs1(k+1,r)决定了k最大是r-1
for (int k = l; k < r; k++)
res = min(res, dfs1(l, k) + dfs1(k + 1, r));
return v = res + s[r] - s[l - 1]; // 记录状态
}
// 搜索出l~r的最大得分
int dfs2(int l, int r) { // 求出最大得分
int &v = g[l][r]; // 利用C++特性定义一个v,简化代码
if (l == r) return v = 0; // 若初始值为0可省略该句
if (v) return v; // l==r时返回0
int res = 0; // 初始值设为0
for (int k = l; k < r; k++)
res = max(res, dfs2(l, k) + dfs2(k + 1, r));
return v = res + s[r] - s[l - 1]; // 记录状态
}
int main() {
scanf("%d", &n);
// 破环成链
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), a[i + n] = a[i];
// 前缀和
for (int i = 1; i <= 2 * n; i++) s[i] = s[i - 1] + a[i];
// 搜索出1-2*n的最小得分
dfs1(1, 2 * n);
// 搜索出1-2*n的最大得分
dfs2(1, 2 * n);
int ans1 = INF, ans2 = 0;
for (int i = 1; i <= n; i++) {
ans1 = min(f[i][n + i - 1], ans1); // 选出最小答案
ans2 = max(g[i][n + i - 1], ans2); // 选出最大答案
}
printf("%d \n%d", ans1, ans2);
return 0;
}