HDU - 1024 Max Sum Plus Plus题解

HDU - 1024 Max Sum Plus Plus题解

题目大意

求关于长度为n的数组的m个子段和的最大值

具体思路

可以从前往后处理

i i i位,如果前一位是被选中的字段,那么这一位可以加进这一个字段。当然第 i i i位也可以从这一位开始从后面若干位单独成为一个字段,也可以不选这一位。

f [ i ] [ j ] f[i][j] f[i][j]为在第 i i i位有 j j j个字段第 i i i位被选中

g [ i ] [ j ] g[i][j] g[i][j]为在第 i i i位有 j j j个字段第 i i i位没被选中

可以列出转移式:

f [ i ] [ j ] = m a x ( f [ i − 1 ] [ j ] , f [ i − 1 ] [ j − 1 ] , g [ i − 1 ] [ j − 1 ] ) + a [ i ] f[i][j]=max(f[i-1][j],f[i-1][j-1],g[i-1][j-1])+a[i] f[i][j]=max(f[i1][j],f[i1][j1],g[i1][j1])+a[i]

g [ i ] [ j ] = m a x ( f [ i − 1 ] [ j ] , g [ i − 1 ] [ j ] ) g[i][j]=max(f[i-1][j],g[i-1][j]) g[i][j]=max(f[i1][j],g[i1][j])

注意事项

题目数据范围给出的 n n n比较大,而且没给出 m m m的范围,注意要用滚动数组

最终结果可能会小于0,注意初始化

注意题目有多组数据

具体实现

#include
long long n,m,a[1000005],f[1000005][2],g[1000005][2],mi=-1e9;
long long Max(long long t1,long long t2){return t1>t2?t1:t2;}
int main(){
    while(scanf("%lld %lld",&m,&n)!=EOF){
        for(int i=1;i<=n;i++){scanf("%lld",&a[i]);f[i][0]=f[i][1]=g[i][0]=g[i][1]=mi;}
        f[0][0]=1;
        for(int i=1;i<=n;i++){
            f[0][i%2]=f[0][(i%2)^1]=0;
            for(int j=1;j<=i&&j<=m;j++){
                f[j][i%2]=Max(f[j][(i%2)^1],Max(g[j-1][(i%2)^1],f[j-1][(i%2)^1]))+a[i];
                g[j][i%2]=Max(f[j][(i%2)^1],g[j][(i%2)^1]);
            }
        }
        printf("%lld\n",Max(f[m][n%2],g[m][n%2]));
    }
}

你可能感兴趣的:(题解,HDU,动态规划,算法,动态规划)