参考巨巨的博客https://www.cnblogs.com/pkgunboat/p/9974886.html
/* * CF1077F1 * 题意: * 给你一个n个元素的数组,从中选取X个元素,并且要保证任意的m个位置中至少有一个元素被选中,问选中元素和的最大值。 * 题解: * 设dp[i][j]表示i位置已经选择了j个元素,所有选中元素的最大和。 * 从i-m+1的位置开始转移,可以写出状态转移方程: * dp[i][j] = max(dp[k][j-1])+a[i] * 意思是,从i-m+1位置到i-1的位置找到已经选取j-1个元素中和最大的一个,再加上自己。 * 最后在n-m+1中找最大值就是答案。因为这些点已经被选取,所以保证了最终答案的合法性。 */ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=255; ll dp[maxn][maxn]; ll a[maxn]; int main () { int N,M,X; cin>>N>>M>>X; for (int i=1;i<=N;i++) scanf("%lld",&a[i]); int tt=N-M+1; if ((tt/M+(tt%M>0))>X) { printf("-1 "); return 0; } int cnt=1; for(int i=1;i<=N;i++){ for(int j=cnt;j<=min(i,X);j++){ for(int k=max(0,i-M);k<i;k++) dp[i][j]=max(dp[k][j-1]+a[i],dp[i][j]); } if (i%M==0) cnt++; } ll ans=0; for (int i=N-M+1;i<=N;i++) ans=max(ans,dp[i][X]); printf("%lld ",ans); }