您的位置:首页 > 其它

1011 最大连续子序列问题

2015-08-24 23:45 351 查看
/*题目描述:

给定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
);

else

printf("0 0 0\n");

}

else

printf("%d %d %d\n",max,buf[start],buf[last]);



}

return 0;

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