HD 1003 Max Sum (最大字段和问题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003
思路一: 刚开始的第一反应就是枚举,枚举一个开头位置i,一个结尾位置j>=i,再求a[i..j]之间所有数的和,找出最大的就可以啦。当然代价也是很高的O(N^3)。
如下代码:
for(int i = 1; i <= n; i++){for(int j = i; j <= n; j++){int sum = 0;for(int k = i; k <= j; k++)sum += a[k]; max = Max(max, sum);}
}
思路二: 我们发现a[i..j]的和不是a[i..j – 1]的和加上a[j]么?所以我们在这里当j增加1的时候把a[j]加到之前的结果上不就可以了么?对!所以我们毫不费力地降低了复杂度,得到了一个新地时间复杂度为O(n^2)的更快的算法。
代码如下:
for(int i = 1; i <= n; i++){int sum = 0;for(int j = i; j <= n; j++){sum += a[j];max = Max(max, sum);}
}
思路三:
动态规划大显身手。我们记录dp[i]表示以a[i]结尾的全部子段中最大的和。我们看一下刚才想到的,我取不取a[i – 1],如果取a[i – 1]则一定是取以a[i – 1]结尾的子段和中最大的一个,所以是dp[i – 1]。 那如果不取dp[i – 1]呢?那么我就只取a[i]孤零零一个好了。注意dp[i]的定义要么一定取a[i]。 那么我要么取a[i – 1]要么不取a[i -1]。 那么那种情况对dp[i]有利? 显然取最大的嘛。所以我们有dp[i] = max(dp[i – 1]+ a[i], a[i]) 其实它和dp[i] = max(dp[i – 1] , 0) + a[i]是一样的,意思是说之前能取到的最大和是正的我就要,否则我就不要!初值是什么?初值是dp[1] = a[1],因为前面没的选了。
这样,我们的时间复杂度是O(n),空间复杂度也是O(n)——因为要记录dp这个数组。我们注意到dp[i] = max(dp[i - 1], 0) + a[i],看它只和dp[i – 1]有关,我们为什么要把它全记录下来呢?为了求所有dp[i]的最大值?不,最大值我们也可以求一个比较一个嘛。
我们定义endmax表示以当前元素结尾的最大子段和,当加入a[i]时,我们有endmax’ = max(endmax, 0) + a[i],然后再顺便记录一下最大值就好了。
老生常谈的问题来了。我们如何找到一个这样的子段?请看伪代码endmax = max(endmax, 0) + a[i], 对于endmax它对应的子段的结尾显然是a[i],我们怎么知道这个子段的开头呢? 就看它有没有被更新。也就是说如果endmax’= endmax + a[i]则对应子段的开头就是之前的子段的开头。否则,显然endmax开头和结尾都是a[i]了。说到这里是不是已经明了呢?那就看看具体的代码吧。
代码如下:
for(int i=1; i<=n; i++){ if(b>0)b+=a[i]; elseb=a[i]; if(b>sum)sum=b; //sum=max(b,sum);}
下面就此题贴出完整代码:
#include<iostream>
#define M 5000+5
#define LL long long
#include<cstring>
using namespace std; LL MaxSum(int n,int a[]){ LL sum=0; int b=0; for(int i=1; i<=n; i++){ if(b>0)b+=a[i]; elseb=a[i]; if(b>sum)sum=b; //sum=max(b,sum);}
return sum;
}
int main(){ int n,a[M],m;LL maxsum; while(cin>>n){for(m=0; m<n; m++) cin>>a[m]; int b[M]; for(m=0; m<n; m++) b[m+1]=a[m]; maxsum=MaxSum(n,b); cout<<maxsum<<endl; }return 0;
}
HD 1003 Max Sum (最大字段和问题)相关推荐
- HD 1003 Max Sum(贪心)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003 Problem Description Given a sequence a[1],a[2],a ...
- hdu 1003 Max Sum (DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003 Max Sum Time Limit: 2000/1000 MS (Java/Others) ...
- HDU.1003 Max Sum
原题 HDU.1003 Max Sum 分类 动态规划 题意 计算从一个序列中最大连续子序列和.对应的起始元素和终止元素的位置. 输入/输出 要求与格式 样例数的确定 最开始一行开始输入样例数 每个样 ...
- 杭电OJ——ACM 1003.Max Sum
Max Sum 杭电OJ--ACM 1003.Max Sum链接入口 问题描述 大意: 给定一个序列a[1],a[2],a[3]-a[n],你需要算出其子序列中的最大值.比如说:给你一个 ...
- hdu 1003 Max Sum 解题报告
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003 Problem Description Given a sequence a[1],a[2],a[3 ...
- hdu 1003 Max Sum
DP可以这里给出非DP程序 题目传送门 1 #include<stdio.h> 2 int main() 3 { 4 int t,n,i,max,m,sum,ki,kj,k,a,b; 5 ...
- [hdu 1003] Max Sum
跟<算法导论(第三版)>上的一样,抄下来的 30 - 60 ms 标准的分治策略 1 #include <stdio.h> 2 3 int A[100000], Lenght; ...
- HDU 1003——Max Sum(动态规划)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003 题目大意:历遍所有数字,找出最大字段和. 解题思路: t和n:记录循环次数和每一段有多少个数字 ...
- 位置子段最大子段和 hdu 1003 max sum ACM的开始
每日一贴,今天的内容关键字为位置子段 这个标题的印象是较比刻深的,我的第一个动态规划标题,也是ACM的开始.最大字段和是较比经典的动归问题.求一个列序的最大子段和的关键点就在于断判一个元素的归属问题, ...
最新文章
- MATLAB中的vpa函数简单实用记录——精度控制
- 普通用户程序使用保留端口 error while loading shared libraries
- POJ2104 K-th Number [分块做法]
- mysql---视图
- React 学习第二天 2018-07-21
- ArrayBlockingQueue原理分析-remove方法
- CGI(通用网关接口)
- java开源播放器_JavaFX/Java8开发的开源音乐播放器
- Linux内核精选文章向读者汇报 | 相遇Linux
- 二维数组,字符串,字符数组
- 读书篇:《细说PHP》三、PHP的语言结构
- PMP培训机构哪家好,求推荐?
- java验证码实现简单_简单实现Java验证码功能
- 从Simulink到PX4——Simulink-PX4插件安装与环境搭建
- Redis学习之lpush命令
- Easyui文件上传格式限制
- 寒假每日一题——贝茜放慢脚步
- I3D【Inflated 3D ConvNet】——膨胀卷积网络用于行为识别
- 时间计算题100道_数学大作战!小学13000道计算题+20000道口算题立即领!
- 图片批量转换成pdf