• 动态规划 最大连续子段和


    子段与子段和的概念:

      给定一个由数字组成的序列,其中一段连续的序列称为一个子段(假设非空),子段中所有的数字和就是为 子段和


    例子:

       {1,2,3,4} ,

       连续子段有 {1} {1,2} {1,2,3} {1,2,3,4} {2,3} {2,3,4} {3,4} {4}

    O(n2) 枚举的做法:

        for(int i=0;i<n;++i){
            long sum = 0;
            for(int j=i;j<n;++j){
                sum += a[j];
                if(sum > nMax){
                    nMax = sum;
                }
            }
        }

    通过观察发现。

    (1) 整个序列都是负数,那么 最大子段和 为 最小的负数 。

    (2) 如果都是正数,那么 最大子段和 就是 整个序列的的和。

    (3) 如果有正有负,那么 最大的子段和 >= 整个序列的最大值,

              那么我们可以假设一个变量sum = 0; 来记录当前的子段和。

              ans 记为 整个序列的最大值

              因为要得到最大的子段 假设{ n1,n2,n3 },那么这个子段前缀 {n1,n2} 一定不会 < 0

              要得到 更大的子段和,我们就不会用 < 0 的子段和 来 拖累 后面的子段和。

              用 ans = max(ans , sum)。来求出结果

    O(n) 动态规划实现代码:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int inf = 0x7fffffff;
    int num[101];
    int main() {
        int N;
        cin >> N;
        for(int i=0;i<N;i++){
            cin >> num[i];
        }
        int ans = -inf;
        for(int i=0;i<N;i++){
            ans = max(ans,num[i]);
        }
        if(ans <= 0){
            cout << ans << endl;
        }else{
            int sum =0;
            for(int i=0;i<N;i++){
                if(sum + num[i] < 0){
                    sum = 0;
                }else{
                    sum += num[i];
                }
                ans = max(ans,sum);
            }
            cout << ans << endl;
        }
        return 0;
    }

    题目:

      HDU1087

    题解:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    int a[1001];
    int dp    [1001]; 
    const int INF = 0x3f3f3f3f;
    int main(){
        int n;
        while(cin >> n&& n){
            for(int i=0;i<n;++i){
                cin >> a[i];
            }
            for(int i=0;i<n;++i){
                dp[i] = a[i];
                for(int j=0;j<i;++j){
                    if(a[i] > a[j]){
                        dp[i] = max(dp[j] + a[i],dp[i]);
                    }
                }
            }
            int maxN = a[0];
            for(int i=0;i<n;++i){
                maxN = max(maxN,dp[i]);
            }
            cout << maxN << endl;
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Linux ln命令
    VSCodeUserSetupx641.67.2
    Where windows subsystem for linux (WSL) File/Directory Location?
    Bash 脚本实例:获取符号链接的目标位置
    叮,GitHub 到账 550 美元「GitHub 热点速览 v.22.26」
    用 40 块搞个游戏机“万能卡”「GitHub 热点速览 v.22.27」
    《HelloGitHub》第 75 期
    termux开启ssh服务
    buildroot使用介绍
    adb常用命令
  • 原文地址:https://www.cnblogs.com/--zz/p/10562029.html
Copyright © 2020-2023  润新知