您的位置:首页 > 其它

杭电1003--连续最长子序列

2015-11-08 22:56 351 查看
Max Sum


Problem Description

Given a sequence a[1],a[2],a[3]……a
, 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

解法1:

# include <iostream>
# include <cstdio>

int main(){

int n,m;
int i,j,k=0;

scanf("%d",&n);
while(n--){
scanf("%d",&m);

int sum = 0,max=-99999;
int t,sta=0,en=0,sta_t=0;
for(i=0;i<m;i++){
scanf("%d",&t);
sum+=t;
if(sum>max){//增长
max = sum;
en = i;
sta = sta_t;//sum<0起的作用
}
if(sum<0){//保存下一个可能存在最大值的起始位置
sum = 0;
sta_t=i+1;
}
}

printf("Case %d:\n",++k);
printf("%d %d %d\n",max,sta+1,en+1);

if(n!=0)printf("\n");

}

return 0;
}


解法2:

# include <iostream>
# include <cstdio>

struct pos{
int r;
int l;
};
pos p[1000000];
int s[1000000];
int main(){

int T;
int n;
scanf("%d",&T);
for(int i=1;i<=T;i++){
scanf("%d",&n);
for(int j=1;j<=n;j++){
scanf("%d",&s[j]);
}

p[1].l = 1;
p[1].r = 1;
for(int k=2;k<=n;k++){
if(s[k-1]+s[k]>s[k]){//说明增长
s[k] =  s[k-1]+s[k];
p[k].l = p[k-1].l;
p[k].r = k;
}else{
s[k] = s[k];
p[k].l=p[k].r=k;
}
}

int maxR = s[1];
int maxId = 1;
for(int j=2;j<=n;j++){
if(s[j]>maxR){
maxR = s[j];
maxId = j;
}
}
if(i!=1)  printf("\n");
printf("Case %d:\n",i);
printf("%d %d %d\n",maxR,p[maxId].l,p[maxId].r);

}

return 0;
}


方法3:

转载:/article/2447402.html

#include<iostream>
#include<vector>
using namespace std;
int main()
{
int T,n,i,start,end,k;
cin>>T;
for(int j=1;j<=T;j++)//因为下面需要输出数字串的起始与结束位置,其与i有关故在此将i设计为从1开始
{
cin>>n;
vector<int>arr(n+1,0); // 这个是表示建立一个容器,里面有n+1个变量,每个变量初始化为0他的作用类似于数组
int sum=0;
start=end=k=1;
int maxn=-1001 ;
for(i=1;i<=n;i++)
{
cin>>arr[i];
sum+=arr[i];
if(maxn<sum)//这一句就是为了找出在数字串的最大值。sum是记录数字串相加的大小,如果有大的就交换值
{

maxn=sum;
end=i;           // 只要是数字串的只在增大就表示着个数字是可以加上去的;所以结束的得地方是和i是同步的

start=k;//设计的时候始终记住就是这两个数是同是在成功的时候可以变得,但是开始的数字就是在不成功的时候也是会变化的, 所以我们要记住在这种情况下,就是要定格
}
if(sum<0)
{
sum=0 ;     //   当sum的结果是负数时,我们就把下一个数组的值交给sum,比如2,-3,这时sum=-1,我们就不要这个结果了,
//       因为他已经不可能是最大值了,就令sum=0;相加是在上面事实现的。

k=i+1;      //     这个时候初始的地方也是要变得如上面的2,-3,原来是start=1,这时直接转到3上因为i=2了。
}

}
cout<<"Case "<<j<<":\n"<<maxn<<" "<<start<<" "<<end<<endl;
if(j!=T)cout<<endl;
}
return 0;
}

下面贴几个例子,如果这几个例子过了就差不多了

-1  -2  -3 10(在此省略了前面的数字,下同)

结果:Case 1: 10 4 4

1 2 3 -100 1 2 3 -100 1 2 2 2 2

结果Case 2:9 9 13

-1 -2 -3 -4 -5

结果:Case  3:-1 1 1

-3 -2 -1 -2 -3

结果:Case 4:-1 3 3

0 0 2 0

结果:Case :2 1 3


方法4:

#include<stdio.h>
int main()
{
int i,ca=1,t,s,e,n,x,now,before,max;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&now);
if(i==1)//初始化
{
max=before=now;//max保留之前算出来的最大和,before存储目前在读入数据前保留的和,now保留读入数据
x=s=e=1;//x用来暂时存储before保留的和的起始位置,当before>max时将赋在s位置,s,e保留最大和的start和end位置
}
else {
if(now>now+before)//如果之前存储的和加上现在的数据比现在的数据小,就把存储的和换成现在的数据,反之就说明数据在递增,可以直接加上
{
before=now;
x=i;//预存的位置要重置
}
else before+=now;
}
if(before>max)//跟之前算出来的最大和进行比较,如果大于,位置和数据就要重置
max=before,s=x,e=i;
}
printf("Case %d:n%d %d %dn",ca++,max,s,e);
if(t)printf("n");
}
return 0;
}


方法5:

# include <iostream>
# include <cstdio>

using namespace std;

int dp[100009],a[100009];
int main(){

int T,n,m;
int i,j,k;
int cnt = 0;
scanf("%d",&T);
while(T--){

scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);

dp[0]=a[0];//dp记录第一个位置
int start=0,end=0;///记录当前最大的dp
int l=0,r=0;//更新每次的下标
int  max_s = a[0];//记录最大的dp
for(j=1;j<n;j++){
if(dp[j-1]>=0){
dp[j] = dp[j-1] + a[j];r=j;//这里可能存在最大的dp,所以需要记录dp的下标
}else{
//走到这里,说明dp[j-1]<0
dp[j] = a[j];l=r=j;//需要记录新的位置
}

if(max_s<=dp[j]){//如果当前的dp取得最大值,需要记录
max_s = dp[j];
start = l;
end = r;

}
}

printf("Case %d:\n",++cnt);
printf("%d %d %d\n",max_s,start+1,end+1);
if(T)  printf("\n");

}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: