计蒜客 难题题库 222 疲倦程度

奶牛Bessie有N分钟时间跑步,每分钟她可以跑步或者休息。若她在第i分钟跑步,可以跑出D_i米,同时疲倦程度增加1(初始为0)。若她在第i分钟休息,则疲倦程度减少1。无论何时,疲倦程度都不能超过M。另外,一旦她开始休息,只有当疲惫程度减为0时才能重新开始跑步。在第N分钟后,她的疲倦程度必须为0。

输入格式:

第一行,两个整数,代表N和M。 接下来N行,每行一个整数,代表D_i。

输出格式:

Bessie想知道,她最多能跑的距离。

N  < =  2000  ,  M  < =  500  ,  D_i  < =  1000

样例1

输入:

5 2
5
3
4
2
10

输出:

9



/* 下面的程序不满足 一旦她开始休息,只有当疲惫程度减为0时才能重新开始跑步
#include<iostream>
using namespace std;

const int maxn = 2002;
const int maxm = 502;
int d[maxn];
int dp[maxn][maxm];     // dp[i][j] 表示前 i 分钟结束,疲劳程度为 j 能跑的最远距离

int main(){
    int n, m;
    cin >> n >> m;
    int i, j;
    for(i = 1; i <= n; ++i){
        cin >> d[i];
    }
    for(i = 1; i <= n; ++i){
        dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);
        for(j = 1; j < m; ++j){
            dp[i][j] = max(d[i] + dp[i - 1][j - 1], dp[i - 1][j + 1]);
        }
        dp[i][m] = d[i] + dp[i - 1][j - 1];
    }
    cout << dp[n][0] << endl;
}
*/



#include<iostream>
using namespace std;

const int maxn = 10010;     // 骗子,说好的 N <= 2000的呢?
const int maxm = 510;
int d[maxn];
int dp[maxn][maxm][2];     
// dp[i][j][0] 表示第 i 分钟不跑的话,前 i 分钟结束,疲劳程度为 j 能跑的最远距离
// dp[i][j][1] 表示第 i 分钟跑的话,前 i 分钟结束,疲劳程度为 j 能跑的最远距离

int main(){
    int n, m;
    cin >> n >> m;
    n = min(n, maxn - 1);
    m = min(m, maxm - 1);
    int i, j;
    for(i = 1; i <= n; ++i){
        cin >> d[i];
    }
    for(i = 1; i <= n; ++i){
        // 不跑
        // 第 i 分钟不跑,结束时疲惫程度为 0 
        dp[i][0][0] = max(max(dp[i - 1][0][0], dp[i - 1][1][0]),
                          max(dp[i - 1][0][1], dp[i - 1][1][1]) );
        // 第 i 分钟不跑,结束时疲惫程度为 j
        for(j = 1; j < m; ++j){
            dp[i][j][0] = max(dp[i - 1][j + 1][0], dp[i - 1][j + 1][1]);
        }
        // 第 i 分钟不跑,结束时疲惫程度为 m,不可能
        dp[i][m][0] = 0;
        
        // 跑
        // 第 i 分钟跑,结束时疲惫程度为 0,不可能
        dp[i][0][1] = 0;
        // 第 i 分钟跑,结束时疲惫程度为 1,前一分钟只能没跑,且疲劳程度为 0
        dp[i][1][1] = d[i] + dp[i - 1][0][0];
        // 第 i 分钟跑,结束时疲惫程度为 j,j >= 2, j - 1 >= 1,所以第 i - 1 分钟只能跑
        for(j = 2; j <= m; ++j){
            dp[i][j][1] = d[i] + dp[i - 1][j - 1][1];
        }
    }
    cout << dp[n][0][0] << endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值