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

来源:互联网 发布:vb6.0获取mac地址 编辑:程序博客网 时间:2024/06/05 16:10
                        Max Sum

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

解法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:
转载:http://blog.csdn.net/hhq420684/article/details/9428687

#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 41 2 3 -100 1 2 3 -100 1 2 2 2 2结果Case 29 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;}
0 0
原创粉丝点击