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

                        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 4

1 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值