• Codeforces 1324E


    题意:

    这个地方一天有 h 个单位时间,Vova打算睡觉睡 n 次觉

    每次睡觉可以睡 a[ i ] 个单位时间或者 a[ i ] - 1 个单位时间,但必须要睡满

    如果醒来的时间在 [ l , r ] 这个范围内,那么这个睡眠时间就很好(答案+1)

    (醒来之后又要马上睡下一次的觉……)

    问Vova该怎么安排这 n 次睡觉,才能使得好的睡眠时间次数最多

    (即每次加上a[ i ]或a[ i ] - 1后的和对h取模,过程中会有多少次落在 l 与 r 之间)

     

    解题思路:

    动态规划,二维数组,一层记录第 i 次睡觉,另一层记录第 i 次睡醒的时间

    dp[ i ] [ j ] 表示已经睡完 i 次觉,且第 i 次睡觉醒来的时间为 j 时,这个过程中答案的最大值

    初始化数组为 -1 ,因为时间从 0 开始,所以特殊处理 dp[0][0] = 0

    i = 1 ~ n      j = 0 ~ h-1

    i 表示第 i 次睡觉,j 表示第 i 次开始睡时的时间

    所以只要 dp[ i-1 ][ j ] != -1,就可以进行状态转移(因为等于 -1 相当于没有任何一个过程到达过时间 j )

    假设这一次要睡 t 个单位时间

    则状态转移方程为

      dp[i][t] = max( dp[i][t] , dp[i-1][j]+( t >= l && t <= r ? 1 : 0 ))

    表示第 i 次醒来,醒来时间为 t 时的最大值,是由第 i 次睡觉,睡觉时间为 j 时的答案 与自身取大 转移而来

     

    (46ms / 2000ms)

    #include<bits/stdc++.h>
    using namespace std;
    int dp[2050][2050];
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        memset(dp,-1,sizeof dp);//初始时,没有访问过的时间设置为-1
        dp[0][0]=0;//如果某个时间有被访问过,那么dp就代表到达这个时间的这个过程中满足题意的最大个数
        int n,h,l,r,i,j,a,t;
        cin>>n>>h>>l>>r;
        for(i=1;i<=n;i++)
        {
            cin>>a;
            for(j=0;j<h;j++)//每种时间都考虑一遍
            {
                if(dp[i-1][j]!=-1)
                {
                    t=(j+a)%h;
                    dp[i][t]=max(dp[i][t],dp[i-1][j]+(t>=l&&t<=r?1:0));//如果下一个位置满足条件,使dp+1
                    t=(j+a-1+h)%h;//两种情况都在第i次进行考虑
                    dp[i][t]=max(dp[i][t],dp[i-1][j]+(t>=l&&t<=r?1:0));
                }
            }
        }
        int ans=dp[n][0];
        for(i=1;i<h;i++)
            ans=max(ans,dp[n][i]);//在最后一次结束后所在的时间中寻找最大值
        cout<<ans<<'
    ';
        
        return 0;
    }

     

  • 相关阅读:
    Mybatis 接口绑定
    Spring AOP
    Spring 基础使用
    Java 类的生命周期
    Mybatis 测试延迟加载
    Mybatis
    eclipse 常用jar包总结
    Web 过滤器参数设置问题
    Web 单元测试
    zabbix监控-自定义监控与报警(二)
  • 原文地址:https://www.cnblogs.com/stelayuri/p/12508208.html
Copyright © 2020-2023  润新知