博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[51nod] 1050 循环数组最大子段和 dp
阅读量:4480 次
发布时间:2019-06-08

本文共 1274 字,大约阅读时间需要 4 分钟。

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-211-413-5-2
Output示例
20
 
最大循环字段和分两种情况:
1.正常的最大字段和 可用dp求
2.从后面某个元素开始,前面某个元素结束,此时中间会空出一段, 设sum(i,j)为这一段的和,sum为       整个数组的和,则maxsum = sum-sum(i,j) ,
 sum(i,j)最小时maxsum最大,即求最小子段和,  如果将数组取反,则最小子段和可转化为最大子段和,用相同的dp可解,再将结果取反就行了。
最终的结果是这两种情况的最大值
#include 
#include
#include
using namespace std;#define LL long long#define MAX 50010int 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\n", ans); return 0;}

转载于:https://www.cnblogs.com/whileskies/p/7226288.html

你可能感兴趣的文章
适配器模式
查看>>
Android中购物车的全选、反选、问题和计算价格
查看>>
GeoServer Rest服务启动匿名认证的配置方法
查看>>
网络流(最大独立点集):POJ 1466 Girls and Boys
查看>>
js立即执行函数
查看>>
cpio命令详解
查看>>
python学习笔记 python实现k-means聚类
查看>>
DNS & CDN & HTTPDNS 原理简析
查看>>
RS485连接CAN——应急用法【worldsing笔记】【待完善】
查看>>
新公司新项目新团队新领导
查看>>
在PADS中如何导出PCB封装库
查看>>
《设计模式之禅》学习笔记(十)
查看>>
160. Intersection of Two Linked Lists
查看>>
深入浅出 Java Concurrency (36): 线程池 part 9 并发操作异常体系[转]
查看>>
面试内容
查看>>
最小公倍数
查看>>
大数乘大数
查看>>
C++继承与派生(原理归纳)
查看>>
PO与PR之间的关系SQL
查看>>
String、StringBuffer和StringBuilder的区别
查看>>