奶牛们打算通过锻炼来培养自己的运动细胞,作为其中一员,贝茜选择的运动方式是每天进行n分钟的晨跑.在每分钟的开始,贝茜会选择下一分钟是用来跑步还是休息.
贝茜的体力限制了她跑步的距离。更具体地,如果贝茜选择在第i分钟内跑步,她可以在这一分钟内跑 d i {d_i} di米,并且她的疲劳度会增加1.不过,无论何时贝茜的疲劳度都不能超过m。
如果贝茜选择休息,那么她的疲劳度就会每分钟减少1,但她须休息到疲劳度恢复到0为止.在疲劳度为0时休息的话,疲劳度不会再变动.晨跑开始时,贝茜的疲劳度为0.
还有,在n分钟的锻炼结束时,贝茜的疲劳度也必须恢复到0,否则她将没有足够的精力来对付这一整天中剩下的事情。
请你计算一下,贝茜最多能跑多少米。
第一行两个正整数 n,m。
接下来n行,每行一个正整数 d i {d_i} di。
输出一个整数,表示在满足所有限制条件的情况下,贝茜能跑的最大距离。
输入输出样例
输入 #1
5 2
5
3
4
2
10
输出 #1
9
说明/提示
对于100%的数据: 1 ≤ n ≤ 1 0 4 , 1 ≤ d i ≤ 1000 , 1 ≤ m ≤ 500. {1\le n \le 10^4 ,1\le d_i \le 1000,1\le m \le 500.} 1≤n≤104,1≤di≤1000,1≤m≤500.
又是一道很适合新手的DP基础题,这道题我们依然可以很容易想到用m和n代表的条件来表示状态,即: f [ i ] [ j ] {f[i][j]} f[i][j]表示第 i {i} i分钟疲劳度为 j {j} j时跑的最大距离,其中我们有两种选择
第一种选择为:
休息到 j = 0 {j=0} j=0,此时若 j {j} j已经为0,则有: f [ i ] [ 0 ] = m a x ( f [ i − 1 ] [ 0 ] , f [ i ] [ 0 ] ) {f[i][0]=max(f[i-1][0],f[i][0])} f[i][0]=max(f[i−1][0],f[i][0]),
否则: f [ i + j ] [ 0 ] = m a x ( f [ i ] [ j ] , f [ i + j ] [ 0 ] ) {f[i+j][0]=max(f[i][j],f[i+j][0])} f[i+j][0]=max(f[i][j],f[i+j][0]);
第二种选择:
继续跑,则有 f [ i + 1 ] [ j + 1 ] = m a x ( f [ i ] [ j ] + a [ i + 1 ] , f [ i + 1 ] [ j + 1 ] ) {f[i+1][j+1]=max(f[i][j]+a[i+1],f[i+1][j+1])} f[i+1][j+1]=max(f[i][j]+a[i+1],f[i+1][j+1]);
(加1是为了防止数组爆掉!)
最后 f [ n ] [ 0 ] {f[n][0]} f[n][0]便是我们要的答案了.(注意初始化: f [ 1 ] [ 1 ] = a [ 1 ] {f[1][1]=a[1]} f[1][1]=a[1]!)
#include
#define N 10505//取一万只多一点点会RE因为数组要装(n+m)!
using namespace std;
int n,m;
int f[N][520],a[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
f[1][1]=a[1];//初始化.
for(int i=1;i<=n;i++)
for(int j=0;j<=min(i,m);j++)
{
if(j==0)f[i][0]=max(f[i-1][0],f[i][0]);//特判,此时没必要休息更新答案
else f[i+j][0]=max(f[i][j],f[i+j][0]);//休息
f[i+1][j+1]=max(f[i+1][j+1],f[i][j]+a[i+1]);//继续跑
}
cout<<f[n][0]<<endl;
return 0;
}