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 }
    代码戳这里
  • 相关阅读:
    如何将已有的本地Git 库推送到远端仓库?
    2017(秋)软工作业: (4)用户体验分析
    微信公众号UX分析—— 学生作业小结
    2017(秋)软工作业: (3)用户体验分析
    珞珈旧时光
    用scp这个命令来通过ssh传输文件
    课堂讨论:分析软件
    2017(秋)软工作业: (2)硬币游戏—— 代码分析与改进
    地铁口的零钱箱:
    Swagger .Net配置
  • 原文地址:https://www.cnblogs.com/THWZF/p/11014316.html
Copyright © 2011-2022 走看看