CodeForces-1324E-Sleeping-Schedule
阅读原文时间:2023年09月03日阅读:6

题意

\(Vova\)有一个睡眠时间表,一天有\(h\)小时,\(Vova\)会睡\(n\)次觉,一次睡一天,在第\(i-1\)次睡醒后,\(Vova\)在\(a_i\)或\(a_i-1\)个小时候可以再次入睡,一开始时间为第\(0\)时(可以视作\(Vova\)刚醒),\(Vova\)在\([l,r]\)区间时睡觉会睡得舒服,问\(Vova\)最多可以睡几次舒服觉

分析

发现第\(i\)次睡眠的时间是由第\(i-1\)次睡眠时间决定的,一个显然的转移,因此这道题采用\(DP\)

首先我们可以设第\(0\)次睡眠时,\(Vova\)是在第\(0\)时刻睡的

假设\(Vova\)在第\(i-1\)次睡眠时在第\(j\)时刻,那么第\(i\)次\(Vova\)可以在第\((j+a_i)\%h\)时刻或者在第\((j+a_i-1)\%h\)时刻睡觉,我们可以记录一个\(vis[i][j]\)表示\(Vova\)在第\(i\)次睡眠时在第\(j\)时刻可以睡

而如果\((j+a_i)\%h\)在\([l,r]\)区间内,则第\(i\)次睡眠在第\((j+a_i)\%h\)时刻的答案数为第\(i-1\)次睡眠时\(j\)时刻的答案数加一,因为有多种方案使得\(Vova\)能在第\(i-1\)次睡眠时在第\(j\)时刻,因此取最大值,可以记录\(dp[i][j]\)表示在第\(i\)次睡眠时在第\(j\)时刻的答案,\(dp[i][(j+a_i)\%h]=max(dp[i-1][j]+1,dp[i][(j+a_i)\%h])\)

如果\((j+a_i)\%h\)不在\([l,r]\)区间内,则\(dp[i][(j+a_i)\%h]=max(dp[i-1][j],dp[i][(j+a_i)\%h])\)

答案可以在每次更新\(dp[i][j]\)时更新

\((j+a_i-1)\%h\)同理

这题不卡空间,可以不使用滚动数组

#pragma GCC optimize(3, "Ofast", "inline")

#include <bits/stdc++.h>

#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define int ll
#define ls st<<1
#define rs st<<1|1
#define pii pair<int,int>
using namespace std;
const int maxn = (ll) 3e5 + 5;
const int mod = 1000000007;
const int inf = 0x3f3f3f3f;
int dp[2005][2005];
bool vis[2005][2005];
int ans;

signed main() {
    start;
    int n, h, l, r;
    cin >> n >> h >> l >> r;
    vis[0][0] = true;
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        for (int j = 0; j < 2000; ++j) {
            if (vis[i - 1][j]) {
                int t = (j + x) % h;
                vis[i][t] = true;
                if (t >= l && t <= r)
                    dp[i][t] = max(dp[i][t], dp[i - 1][j] + 1);
                else
                    dp[i][t] = max(dp[i][t], dp[i - 1][j]);
                ans = max(ans, dp[i][t]);
                t = (j + x - 1) % h;
                vis[i][t] = true;
                if (t >= l && t <= r)
                    dp[i][t] = max(dp[i][t], dp[i - 1][j] + 1);
                else
                    dp[i][t] = max(dp[i][t], dp[i - 1][j]);
                ans = max(ans, dp[i][t]);
            }
        }
    }
    cout << ans;
    return 0;
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章