再探石子合并
分析
见《进阶指南》第334
页。
实现
#include <iostream>
#include <cstring>
using namespace std;
const int N = 5010;
int n, a[N], sum[N];
int f[N][N], p[N][N];
int main () {
scanf("%d", &n);
for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]);
for (int i = 1; i <= n; ++ i) sum[i] = sum[i - 1] + a[i];
memset(f, 0x3f, sizeof(f));
for (int i = 1; i <= n; ++ i) f[i][i] = 0;
for (int i = 1; i <= n; ++ i) p[i][i] = i;
for (int len = 2; len <= n; ++ len) {
for (int l = 1; l + len - 1 <= n; ++ l) {
int r = l + len - 1;
for (int k = p[l][r - 1]; k <= p[l + 1][r]; ++ k) {
if (f[l][k] + f[k + 1][r] < f[l][r]) {
f[l][r] = f[l][k] + f[k + 1][r];
p[l][r] = k;
}
}
f[l][r] += sum[r] - sum[l - 1];
}
}
printf("%d", f[1][n]);
return 0;
}