题目大意:一天有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; }