HDU 1024 Max Sum Plus Plus——滚动数组

点这里

题意: 从长度为n的数组中取出m段不相交的子段,求取出子段的最大和。
题解: 先思考只取一段的最大值问题,很容易能想出定义状态dp[i]表示第i位的最值问题,其状态转移方程为dp[i[ = max(dp[i - 1] + s[i], s[i])。但问题在于我们需要取出m个子段。我们可以按照先计算只取一段的最值,然后再思考取两端的最大和,逐步递推,直到取出m段。
   定义一个数组lmax[i]表示到i为止能取到的最大和,从而状态转移方程变为dp[i] = max(dp[i - 1], lmax[i - 1]) + s[i];。至于我们需要取m个子段,则需要每次更新lmax数组以后,重新更新dp数组表示增加一个子段情况的最大和问题。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;

int n, m, maxx;
int s[N], dp[N], lmax[N];
int main(){
	while(~scanf("%d%d", &m, &n)){
		memset(dp, 0, sizeof dp);
		memset(lmax, 0, sizeof lmax);
		for(int i = 1; i <= n; i++)	scanf("%d", s + i);
		for(int i = 1; i <= m; i++){
			for(int j = i; j <= n; j++)	
				dp[j] = max(dp[j - 1], lmax[j - 1]) + s[j];
			maxx = -0x3f3f3f;
			for(int j = i; j <= n; j++)
				lmax[j] = maxx = max(maxx, dp[j]);
		}
		printf("%d\n", maxx);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值