1324E

题目大意:一天有h个小时,一个人喜欢睡觉,一共睡n次,每次都睡h个小时,开始时间为0,间隔a[i]或a[i]-1个小时开始睡第i次觉,每天都有一个最好时间区间,问这n次觉,最多有多少次是在最好时间内睡的。

题解:定义状态dp[i][j]为第i次觉是在j时刻睡的,那么状态转移方程dp[i][j]=max(dp[i-1][(j-a[i]+h)%h],dp[i-1][(j-a[i]+1+h)%h]+

check(j)。

值得注意的是,不是每个状态都能够到达的,假设dp全部赋值为-1,当

dp[i-1][(j-a[i]+h)%h]==-1&&dp[i-1][(j-a[i]+1+h)%h]==-1时,状态dp[i][j]就无法到达......

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2E3+7;
ll dp[N][N];
ll arr[N];
int main(){
    ll n,h,l,r;
    cin>>n>>h>>l>>r;
    for(ll i=1;i<=n;i++) cin>>arr[i];
    memset(dp,-1,sizeof dp);
    ll c1=arr[1]-1;
    ll c2=arr[1];
    dp[1][c1]=(c1>=l&&c1<=r ? 1:0);
    dp[1][c2]=(c2>=l&&c2<=r ? 1:0);
    ll ans=max(dp[1][c1],dp[1][c2]);
    for(ll i=2;i<=n;i++){
        for(ll j=0;j<h;j++){
            ll c1=(j-arr[i]+h)%h;
            ll c2=(j-arr[i]+1+h)%h;
            if(dp[i-1][c1]<0&&dp[i-1][c2]<0) continue ;
            dp[i][j]=max(dp[i][j],max(dp[i-1][c1],dp[i-1][c2])+(j>=l&&j<=r ? 1:0));
        }
    }
    for(ll i=0;i<h;i++) ans=max(ans,dp[n][i]);
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/Accepting/p/12490712.html