再探石子合并

AcWing-2889-再探石子合并open in new window

分析

见《进阶指南》第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;
}
最后修改于: