zoukankan      html  css  js  c++  java
  • $Poj2228$/洛谷$SP283 Naptime$ 环形$DP$

    Luogu

    一定要记得初始化为-inf!!!

    Description

    在某个星球上,一天由N小时构成。我们称0-1点为第一个小时,1-2点为第二个小时,以此类推。在第i个小时睡觉能恢复Ui点体力。在这座星球上住着一头牛,它每天要休息B个小时,它休息的这B个小时可以不连续,可以分成若干段,但是在每一段的第一个小时不能恢复体力,从第二个小时开始才可以恢复体力。
    为了身体健康,这头牛希望遵循生物钟,每天采用相同的睡觉计划。另外,因为时间是连续的,每天的第N个小时与下一天的第一个小时是相连的,这头牛只需要在N个小时内休息B个小时就够了。
    请你给这头牛安排一个任务计划,使得它每天恢复的体力最多。

     

    Sol

    环形DP,第一反应是断环为链

    所以这里就不讲断环为链了,讲一个另外的方法

    考虑更简单的问题,假设第n个小时与第1个小时不是连续的,即问题是线性的

    阶段与状态:f[i][j][0/1]表示1~i小时内睡了j个小时,第i小时睡了/没睡的最大恢复体力值

    转移:f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1])

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

    初始:f[i][j][0/1]=inf;f[1][1][1]=f[1][0][0]=0;

    注意到,线性其实只比环少了一种情况,就是第1个小时与第n个小时都在睡觉的情况.

    那么我们在线性解题的基础上加上这一情况即可

    具体来说,先执行一遍DP,然后强行让牛在第n小时睡觉,即f[1][1][1]=a[1],再DP一次,用f[n][B][1]更新答案就可以了

    还有,这题可以用滚动数组优化啊!

     

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define Rg register
     5 #define il inline
     6 #define db double
     7 #define ll long long
     8 #define mem(a,b) memset(a,b,sizeof(a));
     9 #define go(i,a,b) for(Rg int i=a;i<=b;++i)
    10 #define yes(i,a,b) for(Rg int i=a;i>=b;--i)
    11 using namespace std;
    12 il int read()
    13 {
    14     int x=0,y=1;char c=getchar();
    15     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    16     while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    17     return x*y;
    18 }
    19 const int N=3831;
    20 int T,n,B,ans,a[N],f[N][N][2];
    21 il void dp()
    22 {
    23     go(i,2,n)
    24         go(j,1,min(i,B))
    25     {
    26         if(i!=j)f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1]);
    27         if(j==1)f[i][j][1]=f[i-1][j-1][0];
    28         else f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1]+a[i]);
    29     }
    30 }
    31 int main()
    32 {
    33     T=read();
    34     while(T--)
    35     {
    36         n=read(),B=read();
    37         go(i,1,n)a[i]=read();
    38         mem(f,128);f[1][1][1]=f[1][0][0]=0;
    39         go(i,1,n)f[i][0][0]=0;
    40         dp();ans=max(f[n][B][0],f[n][B][1]);
    41         mem(f,128);f[1][1][1]=a[1];
    42         go(i,1,n)f[i][0][0]=0;
    43         dp();ans=max(ans,f[n][B][1]);
    44         printf("%d
    ",ans);
    45     }
    46     return 0;
    47 }
    View Code
    光伴随的阴影
  • 相关阅读:
    MyBatisPartA
    概念:漏洞扫描技术
    概念:防火墙技术
    概念:认证技术与访问控制
    概念:为什么要引进密钥管理技术
    概念:数字签名、传统签名和认证
    概念:简述对称密码算法和公钥密码算法的区别
    概念:单向散列函数部分知识点
    Redis单线程QPS效率高的原因,以及redis6.0升级后的变化
    Mydql数据库缓存池Buffer Pool 冷热数据分离
  • 原文地址:https://www.cnblogs.com/forward777/p/11014079.html
Copyright © 2011-2022 走看看