HDU-1024-DP题

HDU-1024-DP局

Max Sum Plus Plus

传送门

这次来写点hdu的博客啦~最近在练习dp哈,都是些简单dp,不过一天玩玩洒洒好像也写不了多少题目=-=不喜欢线上上课啊啊啊=-=
说好的dp局就一定要去完成~

题目的大致意思就是给你一组序列,把这组序列分成指定组,然后组间的元素不能重叠=-=但是可以数量不一样,然后组内元素不允许间断,需要连续的序列=-=,然后问你分成的这么多组的最大和是多少

这是一个dp题,dp题,dp题!!子段和最大值问题

解题思路:
我们用dp[i][j]表示将必须以a[j]结尾为划分的前 j 个元素分为 i 个组的最大和。
这里的状态方程这样描述:
我们考虑第 j 个元素的状态,因为必须要把a[j]划分到某个组去,那么只有两种情况。到底是单独一组还是和其他的一组,于是就分为了以下两种情况
dp[i][j] = max(dp[i][j - 1] + a[j], max(dp[i - 1][k]) + a[j])
dp[i][j - 1] + a[j]代表将前j - 1个数分为 i 组,将a[j]放在前一组里面,也就是说元素组别是连续的,没有间断
max(dp[i - 1][k]) + a[j] (0 < k < j) 在其中找到最大的一个,将前k个分为i - 1组,a[j]单独成为一组,也就是说不同组别中的元素不是连续的

我们采用压缩方式啦~也叫做滚动数组
一维代替二维
max(dp[i - 1][k])是在其中找到上一轮的最大值,所以我们再弄一个数组保存上一轮中对应的最大值就可以啦~
这就是用空间换时间啦~
说明一下:
代码部分的
maxx[j - 1] = ma; ma = max(ma, dp[j]);
这两个不能交换顺序哦,maxx[j - 1] = ma;放在前面是因为要跟新上一次的最大值,如果把maxx[j - 1] = ma;放在后面的话,那就是把这一次的最大值给上一次的,显然不对。

下面是代码部分啦~

#include <bits/stdc++.h>
#define mst(a, n) memset(a, n, sizeof(a))
using namespace std;
const int N = 1e6 + 10;
const int INF = 1e9 + 10;

int a[N];
int dp[N];
int maxx[N];
int ma;
 
int main()
{
	int m, n;
	while (~scanf("%d%d", &m, &n))
	{
		for (int i = 1; i <= n; i++)
		{
			scanf ("%d", &a[i]);
		}
		mst(dp, 0);
		mst(maxx, 0);
		for (int i = 1; i <= m; i++)
		{
			ma = -INF;
			for (int j = i; j <= n; j++)
			{
				dp[j] = max(dp[j - 1] + a[j], maxx[j - 1] + a[j]);
				maxx[j - 1] = ma;
				ma = max(ma, dp[j]);
			}
		}
		cout << ma << endl;
	}
	return 0;
}

我们用ma记录最后要求组别的最大值,就直接用ma存下来啦~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

娃娃酱斯密酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值