George and Job



The new ITone 6 has been released recently and George got really keen to buy it. Unfortunately, he didn't have enough money, so George was going to work as a programmer. Now he faced the following problem at the work.

Given a sequence of n integers p1, p2, ..., pn. You are to choose k pairs of integers:

[l1, r1], [l2, r2], ..., [lk, rk] (1 ≤ l1 ≤ r1 < l2 ≤ r2 < ... < lk ≤ rk ≤ nri - li + 1 = m), 

in such a way that the value of sum  is maximal possible. Help George to cope with the task.

Input

The first line contains three integers nm and k (1 ≤ (m × k) ≤ n ≤ 5000). The second line contains n integers p1, p2, ..., pn(0 ≤ pi ≤ 109).

Output

Print an integer in a single line — the maximum possible value of sum.

Sample test(s)
input
5 2 1
1 2 3 4 5
output
9
input
7 1 3
2 10 7 18 5 33 0
output
61

就是k组数,每组是连续的m个数,求这些数最大和。群里有人推荐这道题,于是来写了一下,题目意思还是很好理解的,很简单的动规思路。 连续m个数,那就对每一个位置都算出前m个数的和,然后就是取k次的一个背包。

dp[i][j]=max(dp[i][j-1],dp[i-1][j-m]+d[j]);

i代表取的次数,j代表到第j个数。但是初始化还有一点细节要处理。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int a[5005];
long long dp[5005], dp1[5005][5005];
long long max(long long a, long long b)
{
	return a > b ? a : b;
}
int main()
{
	int i, j, m, n, ans, k;
	long long sum = 0, pre;
	cin >> n >> m >> k;
	for (i = 1; i <= n; i++)
		cin >> a[i];
	for (i = 0; i < m; i++)
	{
		dp[i] = 0;
		sum = sum + a[i];
	}
	a[0] = 0; j = 0;
	for (i = m; i <= n; i++)
	{
		sum = sum - a[j];
		sum = sum + a[i];
		dp[i] = sum;
		j++;
	}
	for (i = 0; i < m; i++)
		dp1[1][i] = 0;
	for (i = m; i <= n; i++)
		dp1[1][i] = max(dp1[1][i - 1], dp[i]);
	for (i = 2; i <= k; i++)
	{
		for (j = i * m; j <= n; j++)
		{
			dp1[i][j] = max(dp1[i][j - 1], dp1[i-1][j - m] + dp[j]);
		}
	}
	//for (i = 1; i <= n; i++)
	//	cout << dp[i] << " ";
	//cout << endl;
	//for (i = 1; i <= k; i++)
	//{
	//	for (j = 1; j <= n; j++)
	//		cout << dp1[i][j] << " ";
	//	cout << endl;
	//}
	cout << dp1[k][n] << endl;
	return 0;
}

好久不写动规,这次感觉不错,得写专题了,模拟已经够了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值