• (补题 POJ-2228)Naptime(环状DP)


    题目描述

    Goneril是一个非常贪睡的牛,一天有 (n) 个时间段,这牛希望一天可以休息 (B) 个时间段。如果牛在第 $i $ 时刻已经熟睡,他可以得到 (u_i) 的休息。但是如果他在(i) 时刚刚入睡,则不能得到休息。牛可以从前一天晚上睡到第二天。睡觉时间不一定连续。问如何安排睡觉时间,可以使牛得到的休息最大。

    Sample Input

    5 3
    2
    0
    3
    1
    4
    

    Sample Output

    6
    

    解题思路

    环状dp,我们可以将它拆分成线性dp来解答,也就是拆成两个线性dp问题。

    (dp[i][j][0])表示某天前i个小时睡了j个小时(但是第i个小时是醒着的)

    (dp[i][j][1])表示某天前i个小时睡了j个小时(但是第i个小时是睡着的)

    然后就出现了一个问题,那就是如果我们如果第一个时间段就是熟睡的如何去算呢?
    我们可以强行让第一个小时就是熟睡的,即令(dp[1][1][1]=u_1)就可以了。

    为了节省空间我们使用滚动数组代替两个dp数组;

    代码样例

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int maxn=1e6;
    const int inf=0x3f3f3f3f;
    int dp[maxn][2],u[maxn];
    
    int main(){
      int N,B;
      cin >> N >> B;
      for(int i=1; i <= N; i++){
        cin >> u[i];
      }
      memset(dp,-inf,sizeof(dp));
      dp[0][0]=dp[1][1]=0;
      for(int i=2; i <= N; i++){
        for(int j=B ;j > 0; j--){
          dp[j][0]=max(dp[j][0],dp[j][1]);
                dp[j][1]=max(dp[j-1][0],dp[j-1][1]+u[i]);
        }
      }
      int ans=-inf;
      ans=max(ans,max(dp[B][1],dp[B][0]));
      
      memset(dp,-inf,sizeof(dp));
      dp[1][1]=u[1];
      for(int i=2; i <= N; i++){
        for(int j=B ;j > 0; j--){
          dp[j][0]=max(dp[j][0],dp[j][1]);
                dp[j][1]=max(dp[j-1][0],dp[j-1][1]+u[i]);
        }
      }
      ans=max(ans,dp[B][1]);
      cout << ans << endl;
      return 0;
    }
    
  • 相关阅读:
    demo04-默认标签
    demo03-段落标签
    demo02-标题标签
    demo01-注释标签
    前端基础介绍
    xadmin的详细使用
    设置Linux环境变量中文显示乱码
    ES应用
    HTTP协议
    jboss
  • 原文地址:https://www.cnblogs.com/cafu-chino/p/11985136.html
Copyright © 2020-2023  润新知