zoukankan      html  css  js  c++  java
  • 【POJ2228】Naptime

    关于环形dp的处理,我采用的办法是,把整个问题分成两个问题。

    首先我们简化一下问题,假设这个问题不是环形的,那么我们定义f[i][j][1]表示前i个小时休息了j小时,且第i小时正在休息,获得的体力最大值。定义f[i][j][0]表示前i个小时休息了j小时,且第i小时不在休息,获得的体力最大值。显然有f[i][j][0]=max(f[i-1][j][1],f[i-1][j][0]),f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1]+val[i]).初始化f[1][0][0]=f[1][1][1]=0,其余为负无穷,目标为max(f[n][m][1],f[n][m][0]).

    简化问题中,每天的第一个小时是每天的开始,一定不能睡觉。所以一次dp结束之后,我们还需要解决每天的第一个小时入睡的情况,为了解决这种情况,我们使第1个小时与第n个小时都在睡觉,按照上述的方法求解即可,此时初始化f[1][1][1]=val[1],其余为负无穷,目标为f[n][m][1]

    我们执行两次dp,取最优即可。

    另外,n的规模为4000,而状态转移时阶段i只能由i-1转移而来,所以我们可以用滚动数组减少空间的浪费。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 int n,m,a[4000],f[3][4000][3],ans;
     7 int main() {
     8     scanf("%d%d",&n,&m);
     9     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    10     if(!m) {
    11         puts("0");
    12         return 0;
    13     }
    14     memset(f,0xcf,sizeof(f));
    15     f[1&1][0][0]=0;
    16     f[1&1][1][1]=0;
    17     for(int i=2;i<=n;i++) {
    18         for(int j=0;j<=m;j++) {
    19             f[i&1][j][0]=max(f[i-1&1][j][0],f[i-1&1][j][1]);
    20             if(j>0) f[i&1][j][1]=max(f[i-1&1][j-1][0],f[i-1&1][j-1][1]+a[i]);
    21         }
    22     }
    23     ans=max(f[n&1][m][1],f[n&1][m][0]);
    24     memset(f,0xcf,sizeof(f));
    25     f[1&1][1][1]=a[1];
    26     for(int i=2;i<=n;i++) {
    27         for(int j=0;j<=m;j++) {
    28             f[i&1][j][0]=max(f[i-1&1][j][0],f[i-1&1][j][1]);
    29             if(j>0) f[i&1][j][1]=max(f[i-1&1][j-1][0],f[i-1&1][j-1][1]+a[i]);
    30         }
    31     }
    32     ans=max(ans,f[n&1][m][1]);
    33     printf("%d
    ",ans);
    34     return 0;
    35 } 
    AC Code
  • 相关阅读:
    设计模式第一次练习
    区间最大数
    魔方数
    螺旋数
    回文串
    最长单词
    指针的应用之学生成绩
    赛马
    突击队任务
    贪婪之骑士
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10700991.html
Copyright © 2011-2022 走看看