Max Sum



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<=25) 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

#include <stdio.h>

int main () {
		int n;
		int i;
		scanf ("%d",&n);
		for ( i = 0;i < n;i++) {
			int m ;
			int sum = 0;
			int max = - 2000;
			int start = 0;
			int tmp = 0;
			int end = 1;
			int j;
			scanf ("%d",&m);
			for ( j = 0;j < m;j++) {
				int num;
				scanf ("%d",&num);
				sum = sum + num;
				
				if (sum > max) {
					max = sum;
					start = tmp;
					end = j;
				}
				if (sum < 0 ) {
					sum = 0;
					tmp = j+1;
				}
			}
			if (i > 0) {
				printf("\n");
			}
			printf ("Case %d:\n%d %d %d\n",i+1,max,start+1,end+1);
		}
	}
最大子序列和的线性算法及其它算法
来自:http://blog.csdn.net/wptad/article/details/1711857

问题描述:
         给定整数A1, A2,……AN (可能有负数),求I到j的最大值。
例如:
         -2, 11, -4, 13, -5, -2时答案为20
  对于这个问题的算法有很多,当然我要说的是使用“动态规划”算法实现的程序,对于这个算法,我可以说很多人都曾经想到,但是没有想全(因为我就是这样的)。还有一点对于这个问题的动态规划的解法是非常经典的,她的时间复杂度是O(n),也就是线性的。而对于穷举法它的时间复杂度可是O(n3), 这样看来可以巨大的改进了。
  考虑这样的一个问题,我们从最简单的左边开始看,就如上面的例子,-2对于结果有影响吗?回答是没有。那么让我们看下面这样一个例子:
         6, -7, ……
         此时,我们还需要考虑6 和 –7 吗,有些人说要的,因为可能对于6,后面没有比其更大的了,是啊。问题是这样的。那么对于后面的结果分析其有影响吗?这个时候我们可以说没有影响的!
         到现在,上面是不是大家多曾经想到了呢?呵呵,我曾经就想到了,那我们为什么不把这问题,推倒后面呢?动态规划法就是解决这样的一个问题,我们知道此时前面的两个数就是一种最优的子结构(尽管只有2个数,不过是完全可以推广的。)
         书中的算法就告诉我们是如何推广的,我写这样的一篇文章的具体目的也就是为了说明以上的问题,因为我和大家一样都曾经想到了前面的算法,却没有考虑下去。以此感慨!并遗憾!
         那么书中的算法是这样的:(看这个算法之前应该先知道这个问题的“分治法”的求解,这样更让你觉得,这个算法的完美之处。)
 




   Int MaxSubsequenceSum(const int A[], int N)
{
         int ThisSum, MaxSum, j;
         ThisSum = MaxSum = 0;
         For(j=0; j < N; j++)
{
                ThisSum += A[j];
                If (ThisSum > MaxSum)
                       MaxSum = ThisSum;
                Else if(ThisSum < 0)
                       ThisSum = 0;
}
return MaxSum;
} 


 


  对于这个算法的分析(逻辑):


  从左相右相加,若结果不断的增加,那么ThisSum将同MaxSum一起增加,如果遇到负数,那么也加到ThisSum上去,但是此时ThisSum < MaxSum,那么就不加。看ThisSum是不是会回升,若一直不回升,不断或是波浪型的下降,那么当它降到0时,说明前一段与后一段是可以抛弃的。正如有 7 , -8 一样,我们可以不要这两个数,但是我们知道MaxSum依然保存着前一段的最大值,(这就是这个算法中的厉害,我认为)。然后,ThisSum将从后面开始将这个子段进行分析,若有比当前MaxSum大的子段,然后替换(此时可以彻底抛弃前一段)。这样一趟扫描结果也就出来了。
后记:
         对于这个问题,一开始对于分治算法,我们可能很容易想对,而对与动态规划可能我们很难想到(至少我没有那么轻易就想到了)。尽管如此,还是比较庆幸想到了其最优子结构,问题解决到此,当然对于这个问题,我们还是可以用“分治”算法,其时间复杂度为:O(nlogn),也是比较优的,当然没有上面提到的优。   


摘自:http://hi.baidu.com/longchengjiang/blog/item/7a5f2ad894a6d33733fa1c94%2Ehtml


 


补充:如果输入的所有整数为负,最大值为0.,原因是当子序列为空时,包含0个整数,也是子序列,它的和即为0,因为空子序列是连续的,所以总有一个连续子序列,它的和为0。(考虑空子序列的问题:空子序列也是子序列,它的和为0)




PS:MaxSum在这个算法中是一个中间变量,用来记录子问题的最值,而ThisSum是计算子问题的具体方法。


在网上搜到这篇,感觉讲得很通俗,易于理解。


下面附上此类问题的四种算法:


 


#include <iostream.h>
#include <stdio.h>
int MaxSubSum1( const int A[], int N);
int MaxSubSum2( const int A[], int N);
int MaxSubSum3( const int A[], int N);
int MaxSubSum4( const int A[], int N);


const int M = 10;


int main()
{
 int B[M];


    cout<< "请输入 " << M << " 个整数:  "<< endl;
 
 for ( int i=0; i < M; i++ )
 {
  cin>> B[i];
 }


 cout<< " 您输入的 " << M << " 个数为:  "<< endl;


 for ( i = 0; i < M; i++ )
 {
  cout<< B[i] <<", ";
 }


 cout<< " --------------------------------------- " << endl;
 cout<< "四个函数的运算结果分别为:" << endl;
 cout<< "-------------------------" << endl;


    cout<< MaxSubSum1( B, M ) << endl;
    cout<< MaxSubSum2( B, M ) << endl;
    cout<< MaxSubSum3( B, M ) << endl;
    cout<< MaxSubSum4( B, M ) << endl;


 return 0;
}


int MaxSubSum1( const int A[], int N)  /*  第一种方法: 穷举 */
{
 int ThisSum, MaxSum;
 MaxSum = 0;


 for (int i=0; i < N; i++ )
 {
  for ( int j=i; j < N; j++ )
  {
   ThisSum = 0;


   for ( int k=i; k <= j; k++ )
   {
    ThisSum += A[k];
   }


   if ( ThisSum > MaxSum )
   {
    MaxSum = ThisSum;
   }
  }
 }


 return (MaxSum); 
}




int MaxSubSum2( const int A[], int N)  /*  第二种方法: 分治 */
{
 int ThisSum, MaxSum;
 MaxSum = 0;


 for (int i=0; i < N; i++ )
 {
  ThisSum = 0;
  
  for ( int j=i; j < N; j++ )
  {
   ThisSum += A[j];
   
   if ( ThisSum > MaxSum )
   {
    MaxSum = ThisSum;
   }
  }
 }


 return (MaxSum); 
}


 


/*  -----------------------------------------------------------------第三种方法: 二分法 */
static int BiMaxSubSum( const int A[], int Left, int Right );


int MaxSubSum3 ( const int A[], int N ) 
{ 
 return BiMaxSubSum ( A, 0, N - 1 ); 
}


static int BiMaxSubSum( const int A[], int Left, int Right )
{
 int MaxSum, MaxLeftSum, MaxRightSum;
 int LeftBorderSum, RightBorderSum;
 int MaxLeftBorderSum, MaxRightBorderSum;
    int Center;


 if ( Left == Right )
 {
  if ( A[Left] > 0 )
  {
   return A[Left];
  }
  else
  {
   return 0;
  }


 } 
  
 Center = ( Left + Right ) / 2;
 MaxLeftSum = BiMaxSubSum( A, Left, Center );
 MaxRightSum = BiMaxSubSum( A, Center + 1, Right );


 MaxLeftBorderSum = 0;
 LeftBorderSum = 0;
 for ( int i = Center; i >= Left; i-- )
 {
  LeftBorderSum += A[i];
  if ( LeftBorderSum > MaxLeftBorderSum )
  {
   MaxLeftBorderSum = LeftBorderSum;
  }
 }


 MaxRightBorderSum = 0;
 RightBorderSum = 0;
 for ( i = Center + 1; i <= Right; i++ )
 {
  RightBorderSum += A[i];
  if ( RightBorderSum > MaxRightBorderSum )
  {
   MaxRightBorderSum = RightBorderSum;
  }
 }


 MaxSum = ( (MaxRightSum > MaxLeftSum ) ? MaxRightSum : MaxLeftSum );
 int tmp = MaxRightBorderSum + MaxLeftBorderSum;
 return ( ( MaxSum > tmp ) ? MaxSum : tmp );
}


 


 


int MaxSubSum4( const int A[], int N)  /*  第四种方法:  */
{
 int ThisSum, MaxSum;
 ThisSum = MaxSum = 0;


 for (int i=0; i < N; i++ )
 {
  ThisSum += A[i];


  if ( ThisSum > MaxSum )
  {
   MaxSum = ThisSum;
  }
  
  else if ( ThisSum < 0 )
  {
   ThisSum = 0;
  }
 }


 return (MaxSum); 
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值