题目大意

给一个 层的三角形,第 层有 个元素。设第 行第 列的元素为 。一开始只有第一层的元素可选择,其他层的元素 可被选择当且仅当 均被选择。求共选择 个元素的元素和最大值。

题解

DP。设 表示后 列用完,选了 个元素,且第 列共选择了前 行元素的最大和。那么有

其中 表示第 列前 行元素的和。
朴素转移的时间复杂度为 ,可以通过维护 ,即后缀最大值进行优化,优化后的时间复杂度为

#include <bits/stdc++.h>
#define REP(temp, init_val, end_val) for (int temp = init_val; temp <= end_val; ++temp)
#define REPR(temp, init_val, end_val) for (int temp = init_val; temp >= end_val; --temp)
using namespace std;
int read(){
    int f = 1, x = 0;
    char c = getchar();
    while (c < '0' || c > '9'){if(c == '-') f = -f; c = getchar();}
    while (c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
    return f * x; 
}
int n, m, a[55][55], sum[55][55] = {0}, sum2[55][55];
int f[55][1305][55], tri[55];
int g[55][1305][55];
/* inline int q(int x, int y, int bc){
    int rbc = 
    return sum2[y][y + bc]
}*/
void init(){
    REP(i, 1, n)
        REP(j, 1, n - i + 1)
            a[i][j] = read();
    REP(i, 1, n){
        REP(j, 1, n - i + 1)
            sum[j][i] = sum[j - 1][i] + a[j][i];
    }
    REPR(i, n, 1){
        sum2[i][i] = a[1][i];
        REPR(j, i - 1, 1)
            sum2[j][i] = sum2[j + 1][i] + sum[i - j + 1][j];
    }
    /* REP(i, 1, n)
        REP(j, 1, n - i + 1)
            sum[j][i] += sum[j][i - 1]; 
    tri[0] = 0;
    REP(i, 1, n)
        tri[i] = tri[i - 1] + i; */
}
void solve(){
    memset(f, 0xC0, sizeof(f));
    memset(g, 0xC0, sizeof(g));
    f[n + 1][0][0] = g[n + 1][0][0] = 0;
    REPR(i, n, 1){
        REPR(j, n - i + 1, 1){
            int dd = sum[j][i];
            REP(t, j, m){
                f[i][t][j] = g[i + 1][t - j][j - 1] + dd,
                g[i][t][j] = max(f[i][t][j], g[i][t][j + 1]);
            }
        }
        REP(t, 0, m){
            f[i][t][0] = g[i + 1][t][0],
            g[i][t][0] = max(f[i][t][0], g[i][t][1]);
        }
    }
    int ans = 0;
    REP(i, 0, n)
        ans = max(ans, f[1][m][i]);
    printf("%d\n", ans);
}
int main(){
    while (scanf("%d%d", &n, &m) == 2){
        init();
        solve();
    }
    return 0;
}