题目描述:
给定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

//需要用到动态规划

下面这篇文章介绍一下在算法设计中动态规划的最长公共子序列的问题。
最长公共子序列问题所谓,也即是分别给出长度为n和m的字符串A,B,然后找出其中最长公共子序列的最优值和最优解。
所谓最优值,也就是求出这个最长公共子序列的长度;而最优解,就是要求出这个最长最长公共子序列是什么的问题。给个不太恰当的例子:我们中学数学中经常会遇到求函数最值的问题,比如说求出函数 f(x) 的最大值,那么这个最大值就是最优值了;而最优解是什么呢?就是当f(x)取到最大值的时候的 x 值了。

解决的方法其实最简单的就是使用蛮力的方法,列举某一个字符串中的所有子序列,也就是求出这个字符串子序列的幂集;然后分别与另一字符串进行比较。那么由于幂集是 2 的 n 次方。所以其时间复杂度也就是 2 的 n 次方。
那么采用动态规划,可以通过寻求一个求最长公共子序列长度(下面简称LCS)的递推公式。
假设字符串 A = a1 a2 a3 a4.....ai B = b1 b2 b3 b4......bj
L[ i , j ]表示字符串A 和 B的最长公共子序列的长度。
那么:

稍作解释:①假如字符串A B中,有一个是长度为0;那么LCS = 0;
②假如,两个字符串的最后一个字符相同,那么其长度等于,A,B前面字符的匹配结果 +1
③假如,两个字符串的最后一个字符不相同,那么其长度等于,A减去最后一个字符和B进行匹配的结果,B减去最后一个字符和A进行匹配的结果,二者的最大值。

所以对于这个问题的求解,我们可以用一个二维表来进行计算求解,利用上面的公式逐行的填表。二维表的最后一个元素即是问题的最优值。

#include<iostream>
using namespace std;
int max_num(int a,int b);
int main()
{
	int k=0;
	while(cin>>k&&k!=0)
	{
		int aa[10000];
		int bb[10000];
		for(int i=0;i<k;i++)
		{cin>>aa[i];bb[i]=0;}
		bb[0]=aa[0];
		int i,max=bb[0],flag=0;
		for(int i=1;i<k;i++)
		{
			bb[i]=max_num(aa[i],bb[i-1]+aa[i]);
			if(max<bb[i])
			{max=bb[i];flag=i;}//flag指示结尾元素
		}
		int start,temp=max;
		for(int i=flag;i>=0;i--)
		{
			temp-=aa[i];
			if(temp==0)
			{start= i;break;}//start指示开始元素
		}
		if(max<0)
			cout<<0<<' '<<aa[0]<<' '<<aa[k-1]<<endl;
		else
			cout<<max<<' '<<aa[start]<<' '<<aa[flag]<<endl;
	}
	return 0;
}
int max_num(int a,int b)
{
	return a>b?a:b;
}

 posted on 2014-04-29 20:35  mnmlist1  阅读(229)  评论(0编辑  收藏  举报