C - Max Sum Plus Plus HDU - 1024

用二位数组dp[i][j]记录组数为i,前j个数字的最大子段和。

转移方程:

dp[i][j],考虑第j个数,第j个数可以并到前面那一组,此时dp[i][j]=dp[i][j-1]+arr[j],第j个数也可以是作为新的一组,那么dp[i][j]=max(dp[i-1][k])(i-1<=k<=j-1)+arr[j]。我们只要求出前i-1组最大的字段和,然后加上arr[j]这一新的组就行了。

二维数组(o(n^3))的写法

for(int i=1;i<=m;i++)
    for(int j=i;j<=n;j++){
        int tmp=-INF;
        for(int k=i-1;k<=j-1;k++){
            tmp=max(tmp,dp[i-1][k]);
        }
        dp[i][j]=max(dp[i][j-1],tmp)+arr[j];
    }

优化:

注意我们把数组写成2维的目的就是在求第i组时,要用到第i-1组的值,o(n^3)写法中,最后一个for的目的就是求i-1的组数下,前k个数的最大值。所以我们可以用一个数组在dp[i][j]处理出来之后,记录dp[i][j]。当我

再次用到dp[i-1][j]时,可以直接调用了。因此dp[i][j]=max(dp[i][j-1],ma[j-1])+arr[j]。再优化:dp[j]=max(dp[j-1],ma[j-1])+arr[j]。

for(ll i=1;i<=m;i++){//第i组
            tmp=-INF;
            for(ll j=i;j<=n;j++){//考虑第j个人
                dp[j]=max(dp[j-1],ma[j-1])+arr[j];
                ma[j-1]=tmp;
                tmp=max(tmp,dp[j]);
            }
        }

注意:不可以颠倒ma[j-1]=tmp和dp[j]的位置,因为ma[j-1]记录的是i-1时的值。

猜你喜欢

转载自www.cnblogs.com/Accepting/p/12408592.html