题目1011:最大连续子序列

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:7085

解决:3354

题目描述:
    给定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
来源:
2005年浙江大学计算机及软件工程研究生机试真题
答疑:

解题遇到问题?分享解题心得?讨论本题请访问:http://t.jobdu.com/thread-7735-1-1.html


用动态规划的思想。

迭代数组a中的每个数a[i],用cur变量标识从前到a[i](包括a[i])的最大累和。

当cur小于零时归零,意味如果这个从前到a[i]为止的子序列包括a[i], 那么必然和小于0, 索性不要考虑这个子序列,从下一处i+1开始重新计算。

注意到:

1. 如果最大连续子序列不唯一,则输出序号i和j最小的那个

2. 若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。

重要:逻辑思想很好,之前自己想了大半天也没有想出来比较好的方法。

#include <iostream>  
#include <fstream>
using namespace std;  
int k, a[10010];  
int cur, cur_begin;  
int maxx, from, to;  
  
int main()  
{  
	ifstream in;
	in.open("1.txt");
    while (in >> k, k)  
    {  
        maxx = -1;  
        cur = 0;  
        for (int i = 0; i < k; ++ i)  
        {  
            in >> a[i];  
        }  
        for (int i = 0; i < k; ++ i)  
        {  
            cur += a[i];  
            if (maxx < cur)  
            {  
                maxx = cur;  
                from = cur_begin;  
                to = i;  
            }  
            if (cur < 0)  
            {  
                cur_begin = i + 1;  
                cur = 0;  
            }  
        }  
        if (maxx < 0)  
        {  
            cout <<"0"<<a[0]<<" "<<a[k-1]<<endl;  
        } else  
        {  
            cout << maxx << " " << a[from] << " " << a[to] << endl;  
        }  
    }  
    return 0;  
}  

(2)参考一下另外一种思想,感觉其实差不多。

#include<iostream>
#include<fstream>
using namespace std;
const int N = 10010;

int num[N];
int n, ans_l, ans_r, ans_Max;
void solve() {
    int Max = num[0], Sum = num[0];
    int l, r;
    l = r = ans_l = ans_r = 0;
    ans_Max = Max;
    for(int i = 1; i < n; i++) 
	{ 
        if(Sum < 0) 
		{
            Sum = 0;
            l = r = i;
        }
        Sum += num[i];
        r = i;
        if(Sum > Max) 
		{
            ans_r = r;
            ans_l = l;
            Max = Sum;
            ans_Max = Max;
        }
    }
}

int main() 
{
	ifstream in;
	in.open("1.txt");
    while(in>>n,n) 
	{
        for(int i = 0; i < n; i++)
        in>>num[i];
        solve();
        if(ans_Max >= 0)
        cout<<ans_Max<<" "<<num[ans_l]<<" "<<num[ans_r]<<endl;
        else
        cout<<"0"<<" "<<num[0]<<" "<<num[n - 1]<<endl;
    }
    return 0;
}

(3)最后自己写了个比较简单的三层循环,可是提交的时候时间超时。

#include<iostream>
#include <fstream>
using namespace std;
struct order
{
	int first;
	int last;
}index;
int array[10000];
int main()
{
	ifstream in;
	in.open("1.txt");
	int k;	
	in>>k;	
	while(k!=0)
	{
		int flag=0;
		for(int i=0;i<k;i++)
		{
			in>>array[i];
			if(array[i]>=0)
			flag=1;
		}		
		int max=array[0];
		index.first=index.last=0;	
		if(flag==0)
		cout<<"0"<<" "<<array[0]<<" "<<array[k-1]<<endl;
		else
		{
			for(int i=1;i<=k;i++)//序列的个数从1-k 
			{
				for(int j=0;j<=k-i;j++)//序列的相加索引 
				{
					int temp=0;
					for(int l=0;l<i;l++)
					temp=temp+array[j+l];
					if(temp>max)
					{
						max=temp;
						index.first=j;
						index.last=j+i-1;
					}else if(temp==max && j<index.first)
					{
							index.first=j;
							index.last=j+i-1;
					} 
				}
			}
			cout<<max<<" "<<array[index.first]<<" "<<array[index.last]<<endl;	
		} 
		in>>k;
	}	
	return 0;
 } 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值