最大字段和

最大字段和

问题描述
金金最喜欢做有挑战的事情了,比如说求区间最大子段和。
一开始,金金有n个数,第i个数字是ai。
金金又找来了一个新的数字P,并想将这n个数字中恰好一个数字替换成P。要求替换后的最大子段和尽可能大。
金金知道这个题目仍然很简单,所以如果你做不出来,金金就要和你谈一谈了。
注:最大子段和是指在n个数中选择一段区间[L,R](L<=R)使得这段区间对应的数字之和最大。

输入
第一行两个数n,p。
第二行一行n个数ai。

输出
一个数表示答案

输入实例
5 3
-1 1 -10 1 -1

输出示例
5

注意:
样例说明:将第三个数变成3后最大子段和为[2,4]。
数据范围:n<=1000,-1000<=ai,P<=1000。

问题分析
(1)题目含义:本题讲述到金金把一组数中的一个数替换掉之后,求最大的字段和。
(2)本题中根本含义还是求最大字段和,可用for循环将给出的数一一替换,每次循环后找到替换每个数后最大的字段和,再在这些最大的字段和中求最大。
(3)求最大字段和,可采用暴力枚举的形式(即求出这组数中的所有字段,分别求和,求最大)当然这种方法肯定会超时。
(4)我们可以采用dp(动态规划),具体思路如下:
定义一个后边界(在这段区间中,以这个数为最后的那个数(即边界))。
从前往后递推,如果前面的那组数是负值,考虑到加上这个值的最终值只会小,即

C [ i ] = max ⁡ { C [ i − 1 ] + A [ i ] , A [ i ] }    i = 2 , . . . , n C [ 1 ] = A [ 1 ] , \mathrm{C}\left[ \mathrm{i} \right] =\max \left\{ \mathrm{C}\left[ \mathrm{i}-1 \right] +\mathrm{A}\left[ \mathrm{i} \right] ,\mathrm{A}\left[ \mathrm{i} \right] \right\} \,\,\mathrm{i}=2,...,\mathrm{n}\\\mathrm{C}\left[ 1 \right] =\mathrm{A}\left[ 1 \right] , C[i]=max{C[i1]+A[i],A[i]}i=2,...,nC[1]=A[1],

特别注意:存在全为负值的字段,因此我们需提前定义一个足够小的值做初始比较。

具体代码如下:

#include<bits/stdc++.h>
using namespace std;
int INF = 999999999;
int MaxSum(int a[], int n)
{
	int tempSum = 0;
	int maxSum = -INF;
	for (int j = 1; j <= n; j++)   
	{
		tempSum = (tempSum + a[j]) > a[j] ? (tempSum + a[j]) : a[j];
		if (tempSum > maxSum)  
			maxSum = tempSum;

	}
	return maxSum;
}
int main()
{
	int n, p;
	int a[1001];
	cin >> n>>p;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	int maxsum[1001] = {0};
	for (int i = 1; i <= n; i++)
	{
		int temp = a[i];
		a[i] = p;
		maxsum[i]=MaxSum(a,n);
		a[i] = temp;

	}
	int max=maxsum[1];
	for (int i = 2; i <= n; i++)
	{
		if (max < maxsum[i])
		{
			max = maxsum[i];
		}
	}
	cout << max;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值