CF 467C - George and Job (简单区间DP)

题目大意:

有一组数p,选择k组数,每组数是连续的m个数,求最后的大小,看样例比较好理解。


思路:

一开始我的想法便想到了dp[i][j]表示的是到i这个位置,已经取了j组数时候的最大和。

不过接下来的想法跟我的代码实现不大一致,想法没错。

我是想要求dp[i][j],那么他就等于前面dp[k][j-1]+p[i-m~i]

或者是直接从前面dp[k][j]中选择最大的过来。

在代码的实现过程当中过于偏执,考虑到j-1组的开始和终点有一个界限,于是便在这个界限去遍历

殊不知,小于这个界限的,便是0,可有可无,想多了反而更加的复杂。

在者是犯的第二个错误。

并没有想到如何去表示一个区间和,最好的方法便是p[i]表示的是1到i的和

需要哪一段,便去相加减即可。

以致于写的颇为坎坷。

看来今日不宜刷题,得好好反省反省这且燥的心。


感谢美辰巨巨提供的好题~


AC代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long dp[5005][5005];
long long p[5005];
int main()
{
	int n, m, k;
	while (cin >> n >> m >> k)
	{
		p[0] = 0;
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &p[i]);
			p[i] += p[i - 1];
		}
		memset(dp, 0, sizeof(dp));
		for (int i = m; i <= n;i++)
		for (int j = 1; j <= k; j++)
			dp[i][j] = max(dp[i - 1][j], dp[i - m][j - 1] + p[i] - p[i - m]);
	}
	cout << dp[n][k] << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值