感觉是道比较简单的dp,但意外的比较容易做错,主要是细节很容易错。

状态表示:dp[i][j]来表示从前i个物品中取到j个能得到的最大受欢迎程度。

状态转移:对于第i个物品只有拿或者不拿两种选择,因为j我们保证一定能取这么多,所以如果拿第i个物品的话:

dp[i][j]=dp[i-k][j-1]+a[i];从前i-k个物品中拿j-1个的最大值再加上a[i]。

如果不拿第i个物品:

if((j-1)*k<=i-2) dp[i][j]=max({dp[i][j],dp[i-1][j]});判断从i-1个物品中能不能拿到j个,如过可以取最大值。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x)&-x)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
ll dp[10005][101]={0};
ll a[10005]={0};
int n,m,k;
void solve(){
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    dp[1][1]=a[1];
    for(int i=2;i<=n;i++){
        dp[i][1]=max({dp[i-1][1],a[i]});
        for(int j=2;j<=m&&(j-1)*k<=i-1;j++){
            dp[i][j]=dp[i-k][j-1]+a[i];
            if((j-1)*k<=i-2) dp[i][j]=max({dp[i][j],dp[i-1][j]});
        }
    }
    cout<<dp[n][m];
}
int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    solve();
    return 0;
}