zoukankan      html  css  js  c++  java
  • poj2228 Naptime 题解报告

    题目传送门

    【题目大意】

    一天由$n$个小时构成,在第$i$个小时睡觉能够恢复$U_i$点体力。有一头牛要休息$b$个小时,可以不连续,但休息的第1个小时无法恢复体力。前一天的最后一个小时和第二天的第一个小时是连在一起的,求这头牛能恢复的体力最大值。

    【思路解析】

    首先这是一个环形DP问题,所以我们先简化问题,假设前一天的最后一个小时和第二天的第一个小时不是连在一起的,转化为线性问题来处理。设$f[i][j][1]$表示前$i$个小时休息了$j$个小时,并且第$i$个小时在休息的体力恢复最大值,$f[i][j][0]$则表示第$i$个小时不休息的体力恢复最大值。于是可以得到转移方程:

    $$f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1]+u[i])$$

    $$f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1])$$

    初始值:$f[1][0][0]=f[1][1][1]=0$,其余为负无穷

    目标:$max(f[n][b][0],f[n][b][1])$

    然后我们考虑前一天的最后一个小时和第二天的第一个小时连在一起的情况,只需要把初始值改为$f[1][1][1]=U_1$,其余为负无穷,再跑一遍DP,然后答案为$f[n][b][1]$(为了保证第一个小时能恢复体力,前一天的最后一个小时必须休息)。

    【代码实现】

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #define rg register
     5 #define go(i,a,b) for(rg int i=a;i<=b;i++)
     6 #define back(i,a,b) for(rg int i=a;i>=b;i--)
     7 #define mem(a) memset(a,128,sizeof(a));
     8 using namespace std;
     9 const int N=3832;
    10 const int INF=1e9+9;
    11 int n,b,u[N],f[N][2],ans=-INF;
    12 int main(){
    13     scanf("%d%d",&n,&b);
    14     go(i,1,n) scanf("%d",&u[i]);
    15     mem(f);f[0][0]=f[1][1]=0;
    16     go(i,2,n) back(j,min(i,b),1){
    17         f[j][0]=max(f[j][0],f[j][1]);
    18         f[j][1]=max(f[j-1][0],f[j-1][1]+u[i]);
    19     }
    20     ans=max(f[b][1],f[b][0]);
    21     mem(f);f[1][1]=u[1];
    22     go(i,2,n) back(j,min(i,b),1){
    23         f[j][0]=max(f[j][0],f[j][1]);
    24         f[j][1]=max(f[j-1][0],f[j-1][1]+u[i]);
    25     }
    26     ans=max(ans,f[b][1]);
    27     printf("%d
    ",ans);
    28     return 0;
    29 }
    代码戳这里
  • 相关阅读:
    面向对象之补充
    继续面向对象之成员与组合
    面向对象初阶
    模块和包
    异常处理
    [Array]448. Find All Numbers Disappeared in an Array
    [Array]485. Max Consecutive Ones
    [Array] 561. Array Partition I
    [Array] 566. Reshape the Matrix
    opencv3.1线性可分svm例子及函数分析
  • 原文地址:https://www.cnblogs.com/THWZF/p/11014316.html
Copyright © 2011-2022 走看看