1011 最大连续子序列问题

来源:互联网 发布:uml类图转化为java代码 编辑:程序博客网 时间:2024/05/29 18:44
/*题目描述:
    给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和为20。现在增加一个要求,即还需要输出该子序列的第一个和最后一个元素。
输入:
    测试输入包含若干测试用例,每个测试用例占2行,第1行给出正整数K( K< 10000 ),第2行给出K个整数,中间用空格分隔。当K为0时,输入结束,该用例不被处理。
输出:
    对每个测试用例,在1行里输出最大和、最大连续子序列的第一个和最后一个元素,中间用空格分隔。如果最大连续子序列不唯一,则输出序号i和j最小的那个(如输入样例的第2、3组)。若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。
样例输入:
6
-2 11 -4 13 -5 -2
10
-10 1 2 3 4 -5 -23 3 7 -21
6
5 -8 3 2 5 0
1
10
3
-1 -5 -2
3
-1 0 -2
0
样例输出:
20 11 13
10 1 4
10 3 5
10 10 10
0 -1 -2

0 0 0*/


自己的烂代码始终无法AC:

#include <iostream>
#include <stdio.h>
using namespace std;


struct sss
{
    int sum;
    int num11;
    int num22;
};
int main()
{
    int K;
    int i,j,tt;
    int num1,num2;
    int num[10001];
    int max;
    sss s[10001];


    while(scanf("%d",&K)!=EOF)
    {
        if(K==0) break;
        j=0;
        tt=0;
        num1=0;
        for(i=0; i<K; i++)
        {
            scanf("%d",&num[i]);
            if(num[i]<0)
                j++;
            //if(num[i]<=0)
                //tt++;
        }
        //cout<<j<<endl;
        if(j==K)
        {
            printf("0 %d %d\n",num[0],num[K-1]);
            j=0;
            continue;
        }
        //if(tt==K)
        //{
            //printf("0 0 0\n");
            //tt=0;
            //continue;
        //}
        //找到第一个非0元素
        for(i=0; i<K; i++)
        {
            num2=0;
            if(num[i]>=0)
            {
                s[num1].sum=num[i];
                s[num1].num11=i;
                s[num1].num22=i;
                //cout<<"TTTTTTTT i="<<i<<endl;
                //cout<<"s[num1].sum= "<<s[num1].sum<<" s.num11= "<<s[num1].num11<<" s.num22= "<<s[num1].num22<<endl;
                //cout<<"TTTTTTTT\n";
                num1++;
                num2=num[i];
                for(j=i+1; j<K; j++)
                {
                    num2+=num[j];
                    //cout<<"**eee***"<<num2<<" "<<s[num1-1].sum<<endl;
                    if(num2>s[num1-1].sum)
                    {
                        s[num1].sum=num2;
                        s[num1].num11=i;
                        s[num1].num22=j;
                        num1++;
                    }
                }
            }
        }
        //cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
        //cout<<"s[0].sum= "<<s[0].sum<<" s.num11= "<<s[0].num11<<" s.num22= "<<s[0].num22<<endl;
        //cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
        max=0;
        for(j=0; j<num1; j++)
        {
            //cout<<"s["<<j<<"].sum= "<<s[j].sum<<" s.num11= "<<s[j].num11<<" s.num22= "<<s[j].num22<<endl;
            if(s[max].sum<s[j].sum)
                max=j;
        }
        //cout<<"###########################\n";
        printf("%d %d %d\n",s[max].sum,num[s[max].num11],num[s[max].num22]);
    }
    return 0;

}

只好瞻仰大神的代码:

DP

#include <stdio.h>
#include <stdlib.h>
 
void max_lcs(int *arr, int n)
{
    int begin, end, current, max, i, *sum;
    sum = (int *)malloc(sizeof(int) * n);
     
    begin = end = current = 0;
    sum[0] = max = arr[0];
 
    for (i = 1; i < n; i ++) {
        if (sum[i - 1] >= 0) {
            sum[i] = sum[i - 1] + arr[i];
        } else {
            sum[i] = arr[i];
            current = i;
        }
 
        if (sum[i] > max) {
            max = sum[i];
            end = i;
            begin = current;
        }
    }
 
    printf("%d %d %d\n", max, arr[begin], arr[end]);
}
 
 
int main(void)
{
    int i, n, flag, *arr;
 
    while (scanf("%d", &n) != EOF && n != 0) {
        arr = (int *)malloc(sizeof(int) * n);
        for (i = 0, flag = 0; i < n; i ++) {
            scanf("%d", arr + i);
            if (arr[i] >= 0)
                flag = 1;
        }
 
        if (! flag) {   // 均为负数
            printf("0 %d %d\n", arr[0], arr[n - 1]);
        } else {    // 动态规划
            max_lcs(arr, n);
        }
 
        free(arr);
    }
 
    return 0;
}
/**************************************************************
    Problem: 1011
    User: wangzhengyi
    Language: C
    Result: Accepted
    Time:10 ms
    Memory:1068 kb
****************************************************************/


贪心:

当sum<0时,说明当前序列不会对子序列做出贡献,调整i,j重新开始。当sum>max时。更新就OK了~~(*^__^*) 嘻嘻……

#include "stdio.h"

int buf[10001];

int main ()
{
        int n;
        while(scanf("%d",&n)!=EOF,n)
        {
                for(int i=1; i<=n; i++)
                        scanf("%d",&buf[i]);

                int sum = 0,max=0;
                int i=1,j=1;
                int start=1,last=1;
                
                for(int flag=1; flag<=n; flag++)
                {
                        sum+=buf[flag];
                        
                        if(sum<0)
                        {
                                i = flag+1;
                                j = flag+1;
                                sum = 0;
                        }
                        else if(sum>=0)
                        {
                                j++;
                        }
                        if(sum>max) 
                        {
                                max = sum;
                                start = i;
                                last =j-1;
                        }
                }
        
                if(max==0)
                {
                        int flag=0;
                        for(int i=1; i<=n; i++)
                                if(buf[i]<0) flag++;

                        if(flag==n) 
                                printf("0 %d %d\n",buf[1],buf[n]);
                        else
                                printf("0 0 0\n");
                }
                else
                        printf("%d %d %d\n",max,buf[start],buf[last]);
                
        }
        return 0;
}

0 0
原创粉丝点击