zoukankan      html  css  js  c++  java
  • 最大子数列之和问题

    给定一个数组,数组长度为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()!='
    '){
            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()!='
    '){
            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;
    }
  • 相关阅读:
    方向余弦阵,欧拉角,四元数
    贝叶斯公式理解
    mysql安装错误解决办法
    arduino 配置 esp8266
    决策树的python实现
    ppt罗列项排版
    ★-原创性说明-★
    【通知】即日起重启技术博客
    第一篇:你不一定了解的"推荐系统"
    第十篇:K均值聚类(KMeans)
  • 原文地址:https://www.cnblogs.com/yifan2016/p/5326550.html
Copyright © 2011-2022 走看看