最大子序列和

题目链接

#include <stdio.h>
  long long  a[1000006];
  long long maxsum,thissum ;;
int main()
{
 
    int n, i;
    
	while(~scanf("%lld", &n))
	{
		
		
		for(i = 0;i < n;i ++)
		  scanf("%lld", &a[i]);

 		thissum = 0;
 		maxsum = -0x7fffffff;
        for(i = 0;i < n;i ++)
         {
			thissum += a[i];
	
			if(thissum > maxsum)
			maxsum = thissum;
			if(thissum < 0)
			{
				thissum = 0;
			}
	
         } 
        printf("%lld\n",maxsum);
	}
	return 0;
}

做这一题却是废了我不少劲,此题并不难 ,就是个简单的动态规划,刚开始由于数组开的太大却没有放外面,导致程序运行不了,然后就是输出和输入格式不对,导致wa了几次,一下分析是一位同学写的,感觉写的挺好,就给拿来了,呵呵 

分析:

本题首先要想到要用 long long int 来表示最大序列和,另外还要注意一点就是输入的n个数,同样也要用long int 表示,不然也会越界。看到这题有很多方法,相对来说动态规划是比较简洁的。

     下面列出推出其状态转移方程的过程。

      a[i]是输入的原始数列元素,sum[i]是从a[1]~a[i]之间包含a[i]的最大子段和,将sum[i]都求出来后,最最大值即为所求。(sum[]要用long long int)

 假设sum[i-1]已经求出,那么要求sum[i],就要看sum[i-1]加上a[i]和a[i]哪个大 即sum[i]=max(sum[i-1]+a[i],a[i])   这里有点要理解的地方,因为题目中要求的是连续子序列,所以sum[i]=max(sum[i-1]+a[i],a[i])而不是 sum[i]=max(sum[i-1]+a[i],sum[i-1]),因为如果是后面的式子的话其求的的子序列不是连续的,这就不符合题目要求。

    下面就可以写出计算sum[i]的伪码

      sum[0]= a[0];
      int  maxSum = sum[0];
      for (inti = 1; i < n; i++)
      {
             sum[i]= max(sum[i - 1] + a[i], a[i]);
             maxSum= max(maxSum, sum[i]);
      }

  最终maxSum 保存的就是sum[i]中的最大值。


下面使用二分法写的一个求最大子序列和,因为过不了,只是写了一个大概的思路,贴给大家看看:

#include <stdio.h>
#define INFE -65535
int max(int a,int b,int c)
{
	int m = a;
	if(m < b)
	m = b;
	if(m < c)
	m = c;
	return m;
}
int a[1000];
int MAX_sum(int l, int r)
{
	int i, j;
	if(l == r )
	{
		//if(a[l] > 0)
		return a[l];
		//else return 0;	
	}
	
	int mid = (l + r) / 2;
	if(l < r)
	{
		int left_num, right_num, mid_lnum, mid_rnum;
	//	if()
		left_num = MAX_sum(l, mid);
		right_num = MAX_sum(mid + 1, r);
		int Max_lsum, Max_rnum, Max;
		mid_rnum = mid_lnum = 0;
		 Max_lsum = Max_rnum =  INFE;
		for(i = mid;i >= l;i --)
		{
			mid_lnum += a[i];
			if(mid_lnum > Max_lsum)
			Max_lsum = mid_lnum;
		}
		for(i = mid + 1;i <= r;i ++)
		{
			mid_rnum += a[i];
			if(mid_rnum > Max_rnum)
			Max_rnum = mid_rnum;
		}
		Max = Max_rnum + Max_lsum;
		return max(left_num, right_num, Max);
	}
}

int main()
{
	int n, i, j, b;
	while(~scanf("%d", &n))
	{
		for(i = 0;i < n;i ++)
		  scanf("%d", &a[i]);
        b = MAX_sum(0, n-1);
        printf("%d ",b);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值