Max Sum(第一周J题)
来源:互联网 发布:python genetic 编辑:程序博客网 时间:2024/04/30 23:08
Description
Input
Output
Sample Input
25 6 -1 5 4 -77 0 6 -1 1 -6 7 -5
Sample Output
Case 1:14 1 4Case 2:7 1 6
先不说如何解题,重点是先审题!看准输出格式要求,两个例子间换行,也就是最后一个例子后不用换行,因为这个PE了几次特别不值。
解法转自:
最大子序列和问题中的算法四
算法四:
下面介绍一个线性的算法,这个算法是许多聪明算法的典型:运行时间是明显的,但是正确性则很不明显(不容易理解)。
//线性的算法O(N)
long maxSubSum4(const vector<int>& a)
{
long maxSum = 0, thisSum = 0;
for (int j = 0; j < a.size(); j++)
{
thisSum += a[j];
if (thisSum > maxSum)
maxSum = thisSum;
elseif (thisSum < 0)
thisSum = 0;
}
return maxSum;
}
很容易理解时间界O(N)是正确的,但是要是弄明白为什么正确就比较费力了。其实这个是算法二的一个改进。分析的时候也是i代表当前序列的起点,j代表当前序列的终点。如果我们不需要知道最佳子序列的位置,那么i就可以优化掉。
重点的一个思想是:如果a[i]是负数那么它不可能代表最有序列的起点,因为任何包含a[i]的作为起点的子序列都可以通过用a[i+1]作为起点来改进。类似的有,任何的负的子序列不可能是最优子序列的前缀。例如说,循环中我们检测到从a[i]到a[j]的子序列是负数,那么我们就可以推进i。关键的结论是我们不仅可以把i推进到i+1,而且我们实际可以把它一直推进到j+1。
举例来说,令p是i+1到j之间的任何一个下标,由于前面假设了a[i]+…+a[j]是负数,则开始于下标p的任意子序列都不会大于在下标i并且包含从a[i]到a[p-1]的子序列对应的子序列(j是使得从下标i开始成为负数的第一个下标)。因此,把i推进到j+1是安全的,不会错过最优解。注意的是:虽然,如果有以a[j]结尾的某序列和是负数就表明了这个序列中的任何一个数不可能是与a[j]后面的数形成的最大子序列的开头,但是并不表明a[j]前面的某个序列就不是最大序列,也就是说不能确定最大子序列在a[j]前还是a[j]后,即最大子序列位置不能求出。但是能确保maxSum的值是当前最大的子序列和。
对上面的算法进行改进后就可以记录子序列的最后一个下标,但开始的下标依然不好记录,这里有两种办法
1).顺序求一遍最大和子序列后逆序在求一遍,即可求得子序列开始下标。
2).记录子序列长度(代码注释部分),每次更新子序列尾结点的时候更新长度,注意这里不能直接使用所记录的子序列开始的下标,因为有可能子序列开始下标更新了而结束下标未更新(例 5 0 0 0 -10)。
这种算法的缺点就是要特殊考虑数列全为负数的情况。
<span style="font-family:FangSong_GB2312;">#include <iostream>#include <cstdio>#include <cstring>#define M 100005int num[M];using namespace std;int main(){int t;scanf("%d",&t);int cnt=0;int f=1;while(t--){cnt++;int n;scanf("%d",&n);int max=-1001,t;for(int i=0;i<n;i++){scanf("%d",&num[i]);if(num[i]>max){max=num[i];t=i;}}if(max<0)//判断数列是否全为负数 {if(f)printf("Case %d:\n%d %d %d\n",cnt,max,t+1,t+1);elseprintf("\nCase %d:\n%d %d %d\n",cnt,max,t+1,t+1);f=0;continue;}long long sum=0,ans=0;int s=0,e=0;//int b=0,l=0; for(int i=0;i<n;i++)//正向查找 {sum+=num[i];if(sum>=ans){e=i;ans=sum;//l=e-b;}else if(sum<0){sum=0;//b=i;这种记录长度的方法输出下标分别为e-l+1,e+1; }}sum=0;for(int i=n-1;i>=0;i--)//逆向查找 {sum+=num[i];if(sum>=ans){s=i;ans=sum;}else if(sum<0){sum=0;}}if(f){printf("Case %d:\n%lld %d %d\n",cnt,ans,s+1,e+1);//一定要注意输出格式 f=0;}elseprintf("\nCase %d:\n%lld %d %d\n",cnt,ans,s+1,e+1);}return 0;}</span>
- Max Sum(第一周J题)
- J - Max Sum
- 第一周 leetcode算法题(easy)之 Two Sum
- 暑假第一周 J hdu 5702 (结构体排序)
- 杭电acm第1003题Max Sum ( 动态规划)
- 杭电ACM第1003题——Max Sum
- H题 Max sum
- HD1003(Max Sum)
- Max Sum(lis)
- Max Sum(DP)
- HDU1003(Max Sum)
- 第一周:[LeetCode]1. Two Sum
- 算法课第一周作业 | tow sum
- 算法第一周Tow Sum[easy]
- 杭电OJ 第一周 Problem J:吃糖果
- HDOJ 1003题:max sum
- hdu1003 Max Sum (DP)
- HDU--Max sum(DP)
- 多线程---生产者-消费者模型
- Android数据库中的事务
- 使用外部容器运行spring-boot项目:不使用spring-boot内置容器让spring-boot项目运行在外部tomcat容器中
- 知识点归总
- 【Shoi2007】bzoj 1935 园丁的烦恼
- Max Sum(第一周J题)
- iOS中旋转加载动画的实现
- C#结束进程树
- 常用的shell命令
- java实现并发搜索数组元素
- HDU 5900 QSC and Master(区间dp)
- 双飞翼和圣杯布局
- SPS、PPS、IDR
- MD5加密