HDOJ 1003 MaxSum(动态规划 求最大子序列和)

来源:互联网 发布:手机u盘数据恢复 编辑:程序博客网 时间:2024/05/22 06:10

Max Sum

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2137 Accepted Submission(s): 806
Problem 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
25 6 -1 5 4 -77 0 6 -1 1 -6 7 -5
 

Sample Output
Case 1:14 1 4Case 2:7 1 6
 

Author
Ignatius.L


这题一开始,我以为是贪心,找正数,和处理负数,出现各种各样的特例,后来才知道是动态规划。
然后找到递推方程dp[i] = max(dp[i - 1] + dp[i], dp[i]);
推导过程:
1.刚开始数组里存放的是输入的数值。
2.之后数组里存放的都是前面子序列的最大和,这就保证了即使后面出现了一些负数和比这些负数大的正数也不会有影响。
3.如果前一个数组的数值加上当前数组的数值比当前数组的数值要小,也就是dp[i-1]<0了,于是重新从当前这个位置找子序列的最大和。
4.如果前一个数组的数值加上当前数组的数值比当前数组的数值要大,就可以继续往下走。

根据我这个思路做,比较难找到子序列的首位和末位了。
#include<iostream>  #include<cstring>  #include<cmath>  #include<algorithm>  using namespace std;#define max_n 100010int dp[max_n];int main(){int t;cin >> t;int l = 1;while (t--){if (l > 1)cout << endl;//空行memset(dp, 0, sizeof(dp));int n;cin >> n;for (int i = 1; i <= n; i++){cin >> dp[i];}int ans = -1010;//可能数值全为负数int p, q,x;x=p = q = 1;//默认从头开始for (int i = 1; i <= n; i++){if (dp[i - 1] + dp[i] < dp[i])x = i;//找到初始位置dp[i] = max(dp[i - 1] + dp[i], dp[i]);//递推方程if (dp[i] > ans) { ans = dp[i]; q = i; if (x != p)p = x; }//找到结束位置}cout << "Case " << l++ << ":" << endl;cout << ans << " " << p << " " << q << endl;}return 0;}

只要出现3的情况,x就临时充当初始位置,因为不能确定这个子序列是否是有最大和的。