Loading

HDU - 1024 Max Sum Plus Plus 经典最大子段和加强版

求一个数组的m段的最大子段和。

dp[i][j] 表示 当前是第i段,且最后一个元素是a[j]时的最大子段和。那么有两种转移,作为第i段的最后一个元素 或者 第i段的第一个元素。

状态转移方程为dp[i][j]=max(dp[i][j-1]+a[j],dp[i-1][k]+a[j])  i-1<=k<=j-1

首先必须想到这个。

其次这样的数组必然是开不下,这样递推也必然T。

考虑优化。

dp[i -1][k] 总不至于for一遍算的。考虑用一个一维数组递推代替。

注意到数组的第一维是可以滚动的。

于是优化完毕。

int a[maxn];
int dp[maxn];
int max1[maxn];

int main() {
    int n, m, tmp;
    while (~scanf("%d%d", &m, &n)) {
        for (int i = 0; i <= n; i++) dp[i] = 0, max1[i] = 0;
        for (int i = 1; i <= n; i++) a[i] = readint();
        for (int i = 1; i <= m; i++) {
            tmp = -INF;
            for (int j = i; j <= n; j++) {
                dp[j] = max(dp[j - 1], max1[j - 1]) + a[j];
                max1[j - 1] = tmp;
                tmp = max(tmp, dp[j]);
            }
        }
        Put(tmp);
        puts("");
    }
}

 

posted @ 2020-08-07 23:08  MQFLLY  阅读(112)  评论(0编辑  收藏  举报