题目大意:
求一共序列的两个字段最大和。
例如
1 -1 2 2 3 -3 4 -4 5 -5 In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer. 答案是 13
分析:
在做这道题之前,我们先看看求一序列的最大子段是怎样求的。
设a[i]为序列的第i个元素。设b[j]为i到j的子段和的最大值(i从0变化到j),那么当b[j-1]>0时,b[j]=b[i-1]+a[j],
否则 b[j]=a[i];那么b数组中的最大值既所求子段。那么我们可以写下如下程序
#include<iostream> using namespace std; int main() { int a[100]; int n; int b; int i; int sum; cin>>n; for(i=0;i<n;i++) cin>>a[i]; b=a[0]; sum=a[0]; for(i=1;i<n;i++) { if(b>0) b=b+a[i]; else b=a[i]; if(sum<b) sum=b; } cout<<sum<<endl; return 0; }
好的,现在我们通过上面的程序已经会求一个序列的最大子段了,我们在回过来看这道题哦,它是要求两个子段的和最大,那么我们该怎么从求序列的最大子段,求两个子段的最大和呢?我们假设所求两个子序列最大和为sum,两个子序列分别为left和right,这两个子段一个在序列的左边,一个在右边。那么在它们中间必定有一个分割点(这个点即可能被包含在其中一个子段中,也可能不。)设这个点为k,那么left必定是从0到k这个子段的最大子序列(用反证法证明,假设存在在0到k这个范围内的一个子序列nleft的比left大,那么nleft+right将大于sum,这就与上面假设最和为sum矛盾,所以必定不成立比left大的nleft),right必定是从k+1到n-1(n为序列长度)这个子段的最大子序列(证明过程同上),那么我们现在的问题就转换成了求两个最大子序列。我们从左边开始,往右边求出每个点的最大左子段和,保存在b[]数组中,然后再从右边开始,往左边求出每个点的最大右子段和,然后再遍历每个点,求出每个点的两个最大左右子段和,即可得出答案。
代码如下。
#include<iostream> using namespace std; #define len 50010 int main() { int a[len]; int b[len]; int c[len]; int num; int i; int n; scanf("%d",&num); while(num--) { scanf("%d",&n);//注意这道题用cin输入会超时 for(i=0;i<n;i++) { scanf("%d",&a[i]); } //以下代码为从左往右,求出每个点的右边最大子段 b[0]=a[0]; for(i=1;i<n;i++) { if(b[i-1]>0) b[i]=b[i-1]+a[i]; else b[i]=a[i]; } for(i=1;i<n;i++) { if(b[i]<b[i-1]) b[i]=b[i-1]; } //以下代码为从右往左,求出每个点的左边最大子段 c[n-1]=a[n-1]; for(i=n-2;i>=0;i--) { if(c[i+1]>0) c[i]=c[i+1]+a[i]; else c[i]=a[i]; } for(i=n-2;i>=0;i--) { if(c[i]<c[i+1]) c[i]=c[i+1]; } //遍历每个点的子段和,求出最大的那个 int s=b[0]+c[1]; for(i=0;i<n-1;i++) { if(b[i]+c[i+1]>s) s=b[i]+c[i+1]; } printf("%d\n",s); } return 0; }
相关推荐
poj 2488——dfs深度优先遍历 //给行数列数,求问能否遍历,给出字典序的一种遍历
北京大学的在线编程竞赛平台POJ(Problem Online Judge)为初学者提供了一系列的编程题目,其中“北大POJ初级-动态规划”是专门为学习和训练这个主题设立的板块。在这个部分,学员可以通过解题报告和已通过验证(AC...
【强大的POJ分类——各类编程简单题及其算法分类】 POJ,全称为Peking University Online Judge,是北京大学提供的一个在线编程题目平台,支持多种编程语言,包括Pascal、C、C++、Java、Fortran、Python等。这个...
poj2479代码 Maximum sum 对于这道题,我的思路是先从左到右,计算并存储每个节点
c表示有多少种珍珠 ai 表示第i种珍珠所需的数量 pi 表示第i种珍珠的价钱 每买一种珍珠都需要付额外的10 * pi的钱,便宜的珍珠可以用贵的珍珠来代替,求最少的钱的总数。
POJ上的一道题目,自己写的代码,因为想下载别人的, 所以就放上了。
poj经典动态规划题目解题报告,包括经典的动态规划题目20多道,可以作为学习动态规划系统的资料,包括题目: Pku acm 1179 Polygon Pku acm 1125 Stockbroker Grapevine Pku acm 1160 post office Pku ...
### poj dp总结:动态规划分类 #### 概述 动态规划(Dynamic Programming,简称DP)是一种在计算机科学和数学中广泛使用的算法策略,用于解决最优化问题。它通过将复杂问题分解为较简单的子问题来求解,并利用这些...
PKU Online Judge上面很全面的动态规划试题总结。动态规划是ACM考点中最重要的一大类算法之一,对于工作人员来说,动态规划也是实际开发中经常会遇到的算法。这是POJ上面很多DP题目的总结与深刻分析。利于算法学习,...
POJ 1006 源代码——中国剩余定理分析POJ 1006 源代码——中国剩余定理分析POJ 1006 源代码——中国剩余定理分析
在ZOJ和POJ这样的在线判题平台上,有很多动态规划的题目供参赛者练习,通过解决这些题目,可以深入理解和掌握动态规划的运用。 动态规划的适用范围广泛,不仅仅局限于时间相关的动态过程,还可以应用于与时间无关的...
标题中的“动态规划算法poj1088滑雪实验报告”指的是使用动态规划算法解决北京大学ICPC在线测评系统POJ中编号为1088的滑雪问题。这个问题旨在通过一个直观的应用实例,帮助学习者深入理解动态规划的概念,并熟练运用...
【标题】"POJ1015-Jury Compromise" 是一个编程竞赛题目,主要涉及的是动态规划(Dynamic Programming, 简称DP)的算法应用。动态规划是一种解决复杂问题的有效方法,它通过将问题分解成子问题,并存储子问题的解来...
POj 1001源代码——高精度乘单精度POj 1001源代码——高精度乘单精度POj 1001源代码——高精度乘单精度POj 1001源代码——高精度乘单精度
### POJ2485Highways —— JAVA版 #### 题目背景与目标 在虚拟的岛国Flatopia中,尽管地形平坦,但该国却没有一条公共高速公路,这导致了交通上的不便。为了解决这个问题,Flatopia政府计划修建一些高速公路,使得...
POJ 动态规划总结 背包之01背包、完全背包、多重背包详解 Dynamic+Programming 典型的动态规划,用递归下的记忆化搜索来实现 1088 POJ 动态规划加速原理之四边形不等式 基于连通性状态压缩的动态规划问题 对一些DP...
动态规划的解决方案是使用两个指针,一个从左到右扫描数组,计算当前的累计和,并保存为最大和;另一个从右到左扫描,同样计算累计和并与已知的最大和比较。通过这种方式,可以避免重复计算,将时间复杂度降低到线性...