CF1077F1 Solution

题目链接

题解

\(200\)的数据范围容易想到dp。

状态:\(dp[i][j]\):满足条件下前\(i\)个数中选出\(j\)个(必须选\(i\))的最大价值和 。因为我们需要知道\(i\)和上一个选出的相片是否可以覆盖其间的区间,因此必须选\(i\)

初始值:\(dp[i][0]=0,dp[i][j]=-inf\quad (0\le i\le n,1\le j\le x)\)

转移方程:

\[dp[i][j]=max_{p=max(i-k,0)}^{i-1} dp[p][j-1]+a[i]\quad (j>1)\\dp[i][1]=a[i]\quad (i\le k) \]

第一行的方程枚举上一个选出的相片下标\(p\),为使\([p,i]\)区间可被覆盖,\(p\ge max(i-k,0)\)。当只选\(i\)一张相片时则须保证\([1,i]\)可被覆盖,需单独处理。

答案:\(ans=max_{i=n-k+1}^ndp[i][x]\)

因为初始值为\(-inf\),对答案无影响,\(i\)下界为\(1\)亦可。如果\(ans<0\)则无合法状态,输出-1。

AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=210;
int dp[N][N],a[N];//dp[i][j]:满足条件下前i个数中选出j个(必须选i)的最大和 
signed main()
{
	int n,k,x,ans=0;
	scanf("%lld%lld%lld",&n,&k,&x);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	memset(dp,-0x3f,sizeof(dp)); 
	for(int i=0;i<=n;i++) dp[i][0]=0;
	for(int i=1;i<=n;i++)
	{
		if(i<=k) dp[i][1]=a[i];
		for(int j=2;j<=min(i,x);j++)
			for(int p=max(0ll,i-k);p<i;p++) dp[i][j]=max(dp[i][j],dp[p][j-1]+a[i]);
	}
	for(int i=n-k+1;i<=n;i++) ans=max(ans,dp[i][x]);
	if(ans<=0) printf("-1");
	else printf("%lld",ans);
	return 0;
} 
posted @ 2021-02-03 20:58  violet_holmes  阅读(39)  评论(0编辑  收藏  举报