【dp + 滚动数组】HDU 1024 Max Sum Plus Plus

题目

HDU1024

题解

f [ i ] [ j ] f[i][j] 为在选取第 j j 个数字的情况下,将前 j j 个数字分成 i i 组的最大收益。则转移方程式为:
f [ i ] [ j ] = m a x ( f [ i ] [ j 1 ] , f [ i 1 ] [ k ] ) + s [ j ] k { i 1 ,   , j 1 } f[i][j] = max(f[i][j-1], f[i-1][k]) + s[j] \quad k\in \{ i-1, \cdots, j - 1\}

  • 压缩空间复杂度   由转移式可以看出, f [ i ] [ j ] f[i][j] 的值只与 f [ i ] [ j 1 ] f[i][j-1] f [ i 1 ] [ ] f[i-1][*] 有关,所以可以使用滚动数组进行空间压缩。
  • 降低时间复杂度   使用 p r e [ j 1 ] pre[j-1] 来记录 m a x { f [ i 1 ] [ k ] } max\{ f[i-1][k] \} ,边求解 f [ i ] [ j ] f[i][j] ,边记录。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define maxn 1000005
#define inf 0x3f3f3f3f

int s[maxn], f[maxn], pre[maxn];
int n, m, pre_max;

int _max(int a, int b){
    return a > b ? a : b;
}
int main()
{
    int i, j;
    while(~scanf("%d%d", &m, &n)){
        for(i = 1; i <= n; i++){
            scanf("%d", &s[i]);
        }
        for(i = 0; i <= n; i++){f[i] = 0;pre[i] = 0;}
        for(i = 1; i <= m; i++){
            pre_max = -inf;
            for(j = i; j <= n; j++){
                f[j] = _max(f[j - 1], pre[j - 1]) + s[j];
                pre[j - 1] = pre_max;
                pre_max= _max(pre_max, f[j]);
            }
            pre[j - 1] = pre_max;
        }
        printf("%d\n", pre_max);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/running_do_not_stop/article/details/94632803