zoukankan      html  css  js  c++  java
  • [51nod] 1050 循环数组最大子段和 dp

    1050 循环数组最大子段和

    N个整数组成的循环序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑a[n-1],a[n],a[1],a[2]这样的序列)。当所给的整数均为负数时和为0。
    例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
     
    Input
    第1行:整数序列的长度N(2 <= N <= 50000)
    第2 - N+1行:N个整数 (-10^9 <= S[i] <= 10^9)
    Output
    输出循环数组的最大子段和。
    Input示例
    6
    -2
    11
    -4
    13
    -5
    -2
    Output示例
    20
     
    最大循环字段和分两种情况:
    1.正常的最大字段和 可用dp求
    2.从后面某个元素开始,前面某个元素结束,此时中间会空出一段, 设sum(i,j)为这一段的和,sum为       整个数组的和,则maxsum = sum-sum(i,j) ,
     sum(i,j)最小时maxsum最大,即求最小子段和,  如果将数组取反,则最小子段和可转化为最大子段和,用相同的dp可解,再将结果取反就行了。
    最终的结果是这两种情况的最大值
    #include <iostream>
    #include <stdio.h>
    #include <algorithm>
    using namespace std;
    #define LL long long
    #define MAX 50010
    int N;
    int a[MAX];
    
    LL subSum()
    {
        LL ans = 0, sum = 0;
        for (int i = 0; i < N; i++) {
            if (sum < 0)
                sum = a[i];
            else sum += a[i];
            ans = max(ans, sum);
        }
    
        return ans;
    }
    
    int main()
    {
        //freopen("1.txt", "r", stdin);
        scanf("%d", &N);
    
        LL sum = 0;
        for (int i = 0; i < N; i++) {
            scanf("%d", &a[i]);
            sum += a[i];
        }
    
        LL ans1, ans2, ans;
        ans1 = subSum();
        for (int i = 0; i < N; i++)
            a[i] = -a[i];
        ans2 = subSum();
        ans = max(ans1, sum+ans2);
    
        printf("%lld
    ", ans);
        
        return 0;
    }
  • 相关阅读:
    js实现复制功能 javascript
    《架构整洁之道》之组件聚合
    《架构整洁之道》之组件
    js实现导出word
    js实现导出pdf
    《架构整洁之道》之依赖反转原则
    《架构整洁之道》之接口隔离原则
    《架构整洁之道》之里氏替换原则
    解决js地址栏中传递中文乱码的问题
    Windows安装nginx服务
  • 原文地址:https://www.cnblogs.com/whileskies/p/7226288.html
Copyright © 2011-2022 走看看