[Codeforces Round #627]1324E - Sleeping Schedule[dp]

1324E - Sleeping Schedule[ d p dp dp]

time limit per testmemory limit per testinputoutput
2 seconds256 megabytesstandard inputstandard output

Description:

Vova had a pretty weird sleeping schedule. There are h h h hours in a day. Vova will sleep exactly n n n times. The i i i-th time he will sleep exactly after a i a_i ai hours from the time he woke up. You can assume that Vova woke up exactly at the beginning of this story (the initial time is 0 0 0). Each time Vova sleeps exactly one day (in other words, h h h hours).
Vova thinks that the i i i-th sleeping time is good if he starts to sleep between hours l l l and r r r inclusive.
Vova can control himself and before the i i i-th time can choose between two options: go to sleep after a i a_i ai hours or after a i − 1 a_i−1 ai1 hours.
Your task is to say the maximum number of good sleeping times Vova can obtain if he acts optimally.

Input

The first line of the input contains four integers n , h , l n,h,l n,h,l and r r r ( 1 ≤ n ≤ 2000 , 3 ≤ h ≤ 2000 , 0 ≤ l ≤ r < h ) (1≤n≤2000,3≤h≤2000,0≤l≤r<h) (1n2000,3h2000,0lr<h) — the number of times Vova goes to sleep, the number of hours in a day and the segment of the good sleeping time.
The second line of the input contains n n n integers a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an ( 1 ≤ a i < h ) (1≤a_i<h) (1ai<h), where a i a_i ai is the number of hours after which Vova goes to sleep the i i i-th time.

Output

Print one integer — the maximum number of good sleeping times Vova can obtain if he acts optimally.


Example input

7 24 21 23
16 17 14 20 20 11 22

Example output

3

Note

The maximum number of good times in the example is 3 3 3.
The story starts from t = 0 t=0 t=0. Then Vova goes to sleep after a 1 − 1 a_1−1 a11 hours, now the time is 15 15 15. This time is not good. Then Vova goes to sleep after a 2 − 1 a_2−1 a21 hours, now the time is 15 + 16 = 7 15+16=7 15+16=7. This time is also not good. Then Vova goes to sleep after a 3 a_3 a3 hours, now the time is 7 + 14 = 21 7+14=21 7+14=21. This time is good. Then Vova goes to sleep after a 4 − 1 a_4−1 a41 hours, now the time is 21 + 19 = 16 21+19=16 21+19=16. This time is not good. Then Vova goes to sleep after a 5 a_5 a5 hours, now the time is 16 + 20 = 12 16+20=12 16+20=12. This time is not good. Then Vova goes to sleep after a 6 a_6 a6 hours, now the time is 12 + 11 = 23 12+11=23 12+11=23. This time is good. Then Vova goes to sleep after a 7 a_7 a7 hours, now the time is 23 + 22 = 21 23+22=21 23+22=21. This time is also good.


分析:
题意:
Vova第 0 0 0小时是醒着的,他的第一次睡眠应该是从第 0 0 0小时开始
设定一天有 h h h小时,Vova总共可以睡 n n n次(不是一天内睡 n n n次)
如果每次睡着后醒来的时间正好在 [ l , r ] [l,r] [l,r]内,这表示这是一次好睡眠
Vova可以选择第 i i i-th睡 a i a_i ai小时或者 a i − 1 a_i-1 ai1小时
问Vova最多可以有几次好睡眠
做法:
d p [ i ] [ j ] dp[i][j] dp[i][j]表示第 i i i-th睡眠可以在 j j j时醒来,最大的好睡眠的次数
初始化 d p [ i ] [ j ] = − 1 dp[i][j] = -1 dp[i][j]=1,表示全都还不能到达
d p [ 0 ] [ 0 ] = 0 dp[0][0] = 0 dp[0][0]=0,一开始是醒着的
如果 d p [ i − 1 ] [ j ] dp[i-1][j] dp[i1][j]可以到达
那么有两种可能,选择睡 a i a_i ai小时或者 a i − 1 a_i-1 ai1小时
两种都要算一次

dp[i][t] = max(dp[i][t], dp[i-1][j]);
if(t >= l && t <= r)
	dp[i][t] = max(dp[i][t], dp[i-1][j] + 1);
ans = max(ans, dp[i][t]);

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 5;

int a[maxn];
int dp[maxn][maxn];
int n, h, l, r, ans;

void solve(int i, int j, int t) {
    dp[i][t] = max(dp[i][t], dp[i-1][j]);
    if(t >= l && t <= r)
        dp[i][t] = max(dp[i][t], dp[i-1][j] + 1);
    ans = max(ans, dp[i][t]);
}

int main() {
    scanf("%d%d%d%d", &n, &h, &l, &r);
    for(int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    ans = 0;
    memset(dp, -1, sizeof(dp));
    dp[0][0] = 0; // 一开始以为也可以从1开始睡觉
    for(int i = 1; i <= n; ++i) {
        for(int j = 0; j < h; ++j) {
            if(dp[i - 1][j] == -1) continue; // 不可以到达
            solve(i, j, (j + a[i]) % h);
            solve(i, j, (j + a[i] - 1 + h) % h);
        }
    }
    printf("%d\n", ans);
    return 0;
}

/**
7 24 21 23
16 17 14 20 20 11 22
*/





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值