5thweek.problem_A hdu1003最大子段和

Description

Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.

Input

The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).

Output

For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.

Sample Input

2 5 6 -1 5 4 -7 7 0 6 -1 1 -6 7 -5

Sample Output

Case 1: 14 1 4

Case 2: 7 1 6

分析:

DP题。状态转移方程:dp[i]=d[i-1]+a[i]>a[i]?d[i-1]+a[i]:a[i];

错误代码如下:(关键错误和正确代码的对比)

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int m=100005;
 5 int a[m];
 6
 7 int main()
 8 {
 9     int t,k=0;
10     scanf("%d",&t);
11     while(t--)
12     {
13         int n,i,maxn,before,begin=1,end=1;
14         scanf("%d",&n);
15         for(i=1;i<=n;i++)
16         {
17
18             scanf("%d",&a[i]);
19             if(i==1)
20              {
21                  maxn=a[i]; before=a[i];
22              }
23              else
24              {
25                 if(before+a[i]<a[i])
26                 {
27                      before=a[i];
28                      begin=i;
29                 }
30                 else
31                 {
32                    before+=a[i];
33                 }
34
35              }
36              if(before>maxn)
37              {
38                   maxn=before;
39                   //x=begin;
40                   end=i;
41              }
42
43         }
44         k++;
45         printf("Case %d:\n",k);
46         printf("%d %d %d\n",maxn,begin,end);
47         if(t)
48             printf("\n");
49
50     }
51
52     return 0;
53 }

正确代码如下:(用一个特殊点的案例6      :2 3 -6 4 3 -8找出错误!加入一个关键变量j记录当前a[i]位置)

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int m=100005;
 5 int a[m];
 6
 7 int main()
 8 {
 9     int t,k=0;
10     scanf("%d",&t);
11     while(t--)
12     {
13         int n,i,maxn,before,begin=1,end=1,j=1;  //必须用一个j记录当前数a[i]的位置
14         scanf("%d",&n);
15         for(i=1;i<=n;i++)
16         {
17
18             scanf("%d",&a[i]);
19             if(i==1)
20              {
21                  maxn=a[i]; before=a[i];
22
23              }
24              else
25              {
26                 if(before+a[i]<a[i])
27                 {
28                      before=a[i];
29                      j=i;     //记录当前位置,此时begin不改变
30                 }
31                 else
32                 {
33                    before+=a[i];
34                 }
35
36              }
37              if(before>maxn)
38              {
39                   maxn=before;
40                     begin=j;  //只有当before>maxn时再改变
41                   end=i;
42              }
43
44         }
45         k++;
46         printf("Case %d:\n",k);
47         printf("%d %d %d\n",maxn,begin,end);
48         if(t)
49             printf("\n");
50
51     }
52
53     return 0;
54 }
时间: 2024-10-19 19:13:30

5thweek.problem_A hdu1003最大子段和的相关文章

hdu1003 dp(最大子段和)

题意:给出一列数,求其中的最大子段和以及该子段的开头和结尾位置. 因为刚学过DP没几天,所以还会这题,我开了一个 dp[100002][2],其中 dp[i][0] 记录以 i 为结尾的最大子段的和, dp[i][1] 记录以第 i 个数 A[i] 为结尾的和最大子段的开始位置. 对于每一个数 A[i] : 我考察它的前一个数 A[i-1] ,若以 A[i-1] 为结尾的最大子段和 dp[i-1][0] 大于等于 0 ,那么在这个基础上加上 A[i] ,一定大于等于 A[i] 本身,所以以第 i

最大子段和及其拓展

1.最大子段和问题 问题定义:对于给定序列a1,a2,a3--an,寻找它的某个连续子段,使得其和最大(如果某子序列全是负数则定义该子段和为 0).如( -2,11,-4,13,-5,-2 )最大子段是{ 11,-4,13 }其和为20. ·状态设计: dp[i] (1 <= i <= N) 表示以 a[i] 结尾的最大连续子段和. 显然,dp[i] >= 0 (1 <= i <= N) 状态转移方程:dp[i] = max{dp[i-1] + a[i], 0} (2 <

最大子段和(分治法)

#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <map> #define N 1000005 using namespace std; int a[1005]; int calc(int s,int e,int &l,int &r) { int l1,l2,l3,r1,r2,r3; if(s==e) re

最大连续子段和的两种线性算法

问题描述:给一个数组a1,a2,...,an.求这个数组的最大连续子段和.(非空子段) 即,定义Sij=ai+...+aj,则题目要求的是 max{Sij}(1<=i<=j<=n) N^3枚举和优化之后的N^2枚举就不说了,还有NlogN的二分算法也不提,想了解的可以看我的另一篇博客:http://www.cnblogs.com/itlqs/p/5097504.html 这里主要详解两种O(n)的算法. 方法一:动态规划 dp[i]表示以第i位为结尾的最大子段和.那么转移方程就是:dp[

算法重拾之路——最大子段和

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 第二章:动态规划 >最大子段和< 算法描述: ?给定由n个整数(可能为负整数)组成的序列 a1,a2, ... , an ,求该序列形如  从ai 到 aj (i ≤ j)的子段和的最大值.当所有整数均为负整数时定义其最大值为0.根据这个定义,所求的最优值为:

POJ 2479 不相交最大子段和

题目意思还是很好理解的,在一个数列中,找出不相交的两个子串使得其和最大. 解题思路: 对于每个i来说,求出[0 ~ i - 1] 的最大子段和以及[i ~ n - 1]的最大子段和,在加起来,求最大的一个就行了. [0 ~ i - 1]的最大子段和从左向右扫描,[i ~ n - 1] 的最大子段和从右向左扫描即可.时间复杂度为 O(n) source code: //#pragma comment(linker, "/STACK:16777216") //for c++ Compile

蓝桥杯中的最大子段和问题

题目内容: 给定长度为n的整数序列,a[1...n], 求[1,n]某个子区间[i , j]使得a[i]+-+a[j]和最大.或者求出最大的这个和.例如(-2,11,-4,13,-5,2)的最大子段和为20,所求子区间为[2,4]. 输入描述 第一行为一个整数n,表示数组有n个数据,第二行依次输入n个整数 输出描述 计算出n个整数中连续k个数的最大和 输入样例 5 1 2 3 4 5 7 6 -5 5 8 -13 5 7 输出样例 15 14 分析:若记b[j]为由a中有元素1到元素j(1 <=

SPOJ 1043 Can you answer these queries I 求任意区间最大连续子段和 线段树

题目链接:点击打开链接 维护区间左起连续的最大和,右起连续的和.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lson

hdoj 1003 Max Sum 【最大子段和】【贪心】

题意:... 策略:看着像贪心,感觉也是贪心. 很久之前做的,又做了一遍,好题. 代码: #include<stdio.h> #include<string.h> int s[100005]; int main() { int t, i, j, l, st, en, n, v = 1; scanf("%d", &t); while(t --){ scanf("%d", &n); for(i = 1; i <= n; i