E:Sleeping Schedule(DP)

或许更好的阅读体验

Sleeping Schedule

思路

这道题读题就感觉像时 D P DP ,读完题后更加坚定了,这是一道 D P DP 题目。

我们考虑状态转移方程, d p [ i ] [ j ] dp[i][j] 表示在第 i i 次入睡时间是 j j 的时候的时间最优值,所以显然有我们的状态转移方程就是

d p [ i ] [ ( j + a [ i ] ) % n ] = m a x ( ( d p [ i ] [ j + a [ i ] ) % n ) , d p [ i 1 ] [ j ] + 1 dp[i][(j + a[i]) \% n] = max((dp[i][j + a[i]) \% n), dp[i - 1][j] + 1 ,这里的j枚举的是上一次入睡的时间,因为是睡一天嘛,所以下一次睡觉的时间就是 ( j + a [ i ] ) % b (j + a[i]) \% b

当然这里并没有考虑完备,因为我们还有一个时间时是 ( j + a [ i ] 1 ) % n (j + a[i] - 1) \% n ,但是转移过程跟上面是一样的,这里就不多列式子了。

接下来我在代码里说一些我wa过得坑点。

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    } 
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 2e3 + 10;

int dp[N][N], a[N], n, h, l, r;

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false);
    n = read(), h = read(), l = read(), r = read();
    for(int i = 1; i <= n; i++)
        a[i] = read();
    memset(dp, -1, sizeof dp);//初始化,
    dp[0][0] = 0;//只有这个状态是合理的,所以初始化为0.
    for(int i = 1; i <= n; i++)
        for(int j = 0; j < h; j++) {//昨天是在j时入睡的,
            if(dp[i - 1][j] < 0)    continue;//只能从上面一个合理的状态转移过来,所以上一个状态一定要满足是>= 0的,
            if((a[i] + j) % h >= l && (a[i] + j) % h <= r)//隔a[i]
                dp[i][(a[i] + j) % h] = max(dp[i][(a[i] + j) % h], dp[i - 1][j] + 1);
            else
                dp[i][(a[i] + j) % h] = max(dp[i][(a[i] + j) % h], dp[i - 1][j]);
            if((a[i] + j - 1) % h >= l && (a[i] + j - 1) % h <= r)//隔a[i] - 1
                dp[i][(a[i] + j - 1) % h] = max(dp[i][(a[i] + j - 1) % h], dp[i - 1][j] + 1);
            else
                dp[i][(a[i] + j - 1) % h] = max(dp[i][(a[i] + j - 1) % h], dp[i - 1][j]);
        }
    int ans = 0;
    for(int i = 0; i < h; i++)//从0 ~ h - 1枚举,并不是1 ~ n,这点一定注意。
        ans = max(ans, dp[n][i]);
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45483201/article/details/106629841