Max Sum
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 180760 Accepted Submission(s): 42247
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
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
最简单版本的最大连续子序列和,无需多说,直接贪心。注意全是负数的情况即可。
#include<cstdio>
#include<algorithm>
#define INF 1<<30
using namespace std;
int a[100005];
int main(){
int t,tc = 0, _t;
scanf("%d",&t);
_t = t - 1;
while(t--){
int n;
scanf("%d",&n);
if(t != _t)printf("\n");
int tag = 0;
int sum = 0, ans = 0, tmp = 0,l = 0,r = 0;
int maxnum = -INF, index;
for(int i = 0; i < n; i++){
scanf("%d",a+i);
if(a[i]>0)tag = 1;
if(maxnum < a[i])maxnum = a[i], index = i;
sum += a[i];
if(sum < 0) sum = 0,tmp = i+1;
if(ans < sum){
l = tmp;
r = i;
ans = sum;
}
}
if(!tag){
printf("Case %d:\n%d %d %d\n",++tc, maxnum, index+1,index+1);
continue;
}
printf("Case %d:\n%d %d %d\n",++tc,ans,l+1,r+1);
}
return 0;
}
Max Sum Plus Plus
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 20804 Accepted Submission(s): 6925
Problem Description
Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you are faced with a more difficult problem.
Given a consecutive number sequence S 1, S 2, S 3, S 4 ... S x, ... S n (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ S x ≤ 32767). We define a function sum(i, j) = S i + ... + S j (1 ≤ i ≤ j ≤ n).
Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i 1, j 1) + sum(i 2, j 2) + sum(i 3, j 3) + ... + sum(i m, j m) maximal (i x ≤ i y ≤ j x or i x ≤ j y ≤ j x is not allowed).
But I`m lazy, I don't want to write a special-judge module, so you don't have to output m pairs of i and j, just output the maximal summation of sum(i x, j x)(1 ≤ x ≤ m) instead. ^_^
Given a consecutive number sequence S 1, S 2, S 3, S 4 ... S x, ... S n (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ S x ≤ 32767). We define a function sum(i, j) = S i + ... + S j (1 ≤ i ≤ j ≤ n).
Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i 1, j 1) + sum(i 2, j 2) + sum(i 3, j 3) + ... + sum(i m, j m) maximal (i x ≤ i y ≤ j x or i x ≤ j y ≤ j x is not allowed).
But I`m lazy, I don't want to write a special-judge module, so you don't have to output m pairs of i and j, just output the maximal summation of sum(i x, j x)(1 ≤ x ≤ m) instead. ^_^
Input
Each test case will begin with two integers m and n, followed by n integers S
1, S
2, S
3 ... S
n.
Process to the end of file.
Process to the end of file.
Output
Output the maximal summation described above in one line.
Sample Input
1 3 1 2 3 2 6 -1 4 -2 3 -2 3
思路:动态规划。dp[ i ][ j ]表示前 j 个元素分成 i 段得到的最大和,则有状态转移方程dp[ i ][ j ]=max(dp[ i ][ j-1], dp[ i-1 ][ k ]) + a[ j ],k: i-1 -> j-1,表示第 j 个元素的两种情况:加入前一个连续子串和自己重新成为一个串。那么题目大概就差不多了,注意优化成一维的形式(或者滚动数组),并且为了减小复杂度,要开一个数组记录i - 1行的dp值。
#include<cstdio>
const int maxn = 1000005, INF = 1<<30;
int pre[maxn], dp[maxn], a[maxn], maxnum,m ,n;
int main(){
while(~scanf("%d %d",&m,&n)){
for(int i = 1; i <= n; i++) scanf("%d",a+i),dp[i]=pre[i]=0;
dp[0]=pre[0]=0;
for(int i = 1; i <= m; i++){
maxnum = -INF;
for(int j = i; j <= n; j++){
dp[j] = (dp[j-1]>pre[j-1]?dp[j-1]:pre[j-1])+a[j];
pre[j-1] = maxnum;
maxnum = maxnum>dp[j]?maxnum:dp[j];
}
}
printf("%d\n",maxnum);
}
return 0;
}