(ACWing4378)选取数对(动态规划)

题目链接:4378. 选取数对 - AcWing题库

分析:就是给你n个数,然后让你选k个区间,每个区间选m个数,问你所选的k个区间所有数的最大和是多少。

这显然是一道动态规划题目,设f[i][j]表示考虑到第i个数且已经选了j个区间的所有数的最大和。然后我们每次考虑是否要选取当前数,如果选的话那么当前数就是我们所选取的第j个区间的右端点,那么这个时候f[i][j]=f[i-m][j-1],因为我们要是选当前数作为第j个区间的右端点,那么第j-1个区间中的数就要从i-m个数及之前开始选了。如果我们不选当前数,那么f[i][j]=f[i-1][j],就是从前i-1个数中选j个区间。这样就完成了本道题目的更新。

下面是代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=5e3+10;
ll f[N][N],sum[N];//f[i][j]表示到达第i个位置选取j个区间的所选数的和的最大值
int main()
{
	int n,m,k;
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&sum[i]);
		sum[i]+=sum[i-1];
	}
	f[m][1]+=sum[m];
	for(int i=m+1;i<=n;i++)
	for(int j=1;j<=min(k,i/m);j++)
		f[i][j]=max(f[i-m][j-1]+sum[i]-sum[i-m],f[i-1][j]);
	printf("%lld",f[n][k]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值