从正面寻找最大值太难了,不如换个思维,从反面来找答案。既然题目是要求最大的训练效果,那我们就去找因为休息而浪费的最小训练效果,最后再让总的训练效果减去浪费的最小训练效果就得出答案了,这样就方便多了。要求第i天浪费的最小值,只需要找到[i-k-1,i-1]这个区间里浪费的最小值进行了。因此状态转移方程只有一种: dp[i]=1e18; for(int j=i-k-1;j<i;j++) { dp[i]=min(dp[j],dp[i]); } dp[i]+=arr[i];
#include<iostream>
using namespace std;
#define int long long
const int da=1e18;//所有的训练效果加起来最大不超过1e18
int n,k;
int sum;
int arr[100010];
int dp[100010];
signed main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>arr[i],sum+=arr[i];
for(int i=1;i<=n;i++)
{
int j=i-k-1;
if(j<0)
j=0;
//j可能小于0,因此当就j<0时,使其等于0,确保数组不会越界
dp[i]=da;
for(;j<i;j++)
{
dp[i]=min(dp[j],dp[i]);
}
dp[i]+=arr[i];
}
int ans_min =da;
for(int i=n;i>=n-k;i--)
{
ans_min=min(ans_min,dp[i]);
}
cout<<sum-ans_min;//让总的训练效果减去休息浪费的最少训练效果
return 0;
}