最大子数列之和问题

给定一个数组,数组长度为n,数组中每个元素为一个整数(其中有正数,负数,零),求一和最大的子数组

这是一道老生常谈的动态规划问题,也是我大一学算法时遇到的第一道动态规划问题,当时觉得解法非常精妙,从此爱上了算法。

题目的具体解法为是dp[i][0]表示前i项数列不含最后一项(第i项)时的子数列之和的最大值,dp[i][1]表示前i项数列含最后一项的子数列之和最大值

很明显dp[i][0]=max(dp[i-1][1],dp[i-1][1]),dp[i][1]=max(dp[i-1][1]+a[i],a[i]);

但是从上面的状态转移方程可以发现,每一项只与前一项有关,所以状态转移过程中,无需记录多余的状态,只记录该状态的前一种状态即可,所以描述子状态二维数组完全可以使用 dp1 和 dp2 这两个数来代替,从而优化了空间发杂度

最终优化完成的代码如下:

#include<iostream>
#include<string>
using namespace std;
int main(){
    long long dp1,dp2,a[10000],ans;
    int n=1;
    cin>>a[0];
    while(getchar()!='\n'){
        cin>>a[n++];
    }
    dp1=-99999999;ans=dp2=a[0];//为避免全为负数
    for(int i=1;i<n;i++){
        dp1=max(dp1,dp2);
        dp2=max(dp2+a[i],a[i]);    
    }
    ans=max(dp1,dp2);    
    cout<<ans<<endl;
    return 0;
}

 

第二,如果上述数列首尾相接,那样的话,其实和原来的问题依然一样,原来的问题可以看做数列在第一个元素和最后一个元素之间比存在一个断口,现在首尾相接,只要枚举一下断口的位置即可,具体代码如下:

#include<iostream>
#include<string>
using namespace std;
int main(){
    long long dp1,dp2,a[10000],ans;
    int n=1;
    cin>>a[0];
    while(getchar()!='\n'){
        cin>>a[n++];
    }
    for(int j=0;j<n;j++){
        int k=j;
        dp1=-99999999;ans=dp2=a[k];
        for(int i=1;i<n;i++){
            k++;k%=n;        
            dp1=max(dp1,dp2);
            dp2=max(dp2+a[k],a[k]);    
        }
        ans=max(ans,max(dp1,dp2));    
    }
    cout<<ans<<endl;
    return 0;
}

 

转载于:https://www.cnblogs.com/yifan2016/p/5326550.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值