• 【dp】bzoj1613: [Usaco2008 Jan]Running贝茜的晨练计划


    还记得这是以前看上去的不可做题……

    Description

    奶牛们打算通过锻炼来培养自己的运动细胞,作为其中的一员,贝茜选择的运动方式是每天进行N(1<=N<=10,000)分钟的晨跑。在每分钟的开始,贝茜会选择下一分钟是用来跑步还是休息。贝茜的体力限制了她跑步的距离。更具体地,如果贝茜选择在第i分钟内跑步,她可以在这一分钟内跑D_i(1<=D_i<=1,000)米,并且她的疲劳度会增加1。不过,无论何时贝茜的疲劳度都不能超过M(1<=M<=500)。如果贝茜选择休息,那么她的疲劳度就会每分钟减少1,但她必须休息到疲劳度恢复到0为止。在疲劳度为0时休息的话,疲劳度不会再变动。晨跑开始时,贝茜的疲劳度为0。还有,在N分钟的锻炼结束时,贝茜的疲劳度也必须恢复到0,否则她将没有足够的精力来对付这一整天中剩下的事情。请你计算一下,贝茜最多能跑多少米。

    Input

    * 第1行: 2个用空格隔开的整数:N 和 M
    * 第2..N+1行: 第i+1为1个整数:D_i

    Output

    * 第1行: 输出1个整数,表示在满足所有限制条件的情况下,贝茜能跑的最大距离


    题目分析

    我们可以自然地想到二维dp,用$f[i][j]$表示$i$分钟时疲劳度为$j$的最大答案值。

    这题难就难在转移有限制条件:如果接下去要休息那么必须继续休息到0才行

    考虑这个限制条件的另一种表述方式:我们的$f[i][j]$只能转移到$f[i+j][0]$,而不能使$f[i+k][j-k]$都更新一遍。原因是若$f[i+k][j-k]$被更新了,它在之后的转移中就会被当做是一个独立的状态而不被限制。

    那么就考虑完了这个限制条件,套上去做就可以了。

    还有要注意的一点是:奶牛在疲劳度为0的时候可以继续休息。样例非常良心地给出了这种情况。

     1 #include<bits/stdc++.h>
     2 
     3 int n,m;
     4 int f[10013][503],d[10013];
     5 
     6 int main()
     7 {
     8     scanf("%d%d",&n,&m);
     9     for (int i=1; i<=n; i++) scanf("%d",&d[i]);
    10     for (int i=1; i<=n; i++)
    11     {
    12         for (int j=0; j<=std::min(m, i); j++)
    13             if (j){
    14                 f[i][j] = std::max(f[i-1][j-1]+d[i], f[i][j]);
    15                 if (i+j <= n)
    16                     f[i+j][0] = std::max(f[i+j][0], f[i][j]);
    17             }else f[i][j] = std::max(f[i][j], f[i-1][j]);
    18     }
    19     printf("%d
    ",f[n][0]);
    20     return 0;
    21 }

    END

  • 相关阅读:
    关于线程池的线程复用
    Java线程锁之意难平的读写锁
    Java8之StringJoiner
    springboot整合thymeleaf
    一维数组转二叉树、注解回滚、eclipse配置代码自动补全
    Java之线程锁
    关于工作中的一些总结
    关于shiro的猜测
    Java之扫描不到mapper
    网页中引用css样式
  • 原文地址:https://www.cnblogs.com/antiquality/p/9042547.html
Copyright © 2020-2023  润新知