Codeforces 1324E - Sleeping Schedule

题意:

这个地方一天有 h 个单位时间,Vova打算睡觉睡 n 次觉

每次睡觉可以睡 a[ i ] 个单位时间或者 a[ i ] - 1 个单位时间,但必须要睡满

如果醒来的时间在 [ l , r ] 这个范围内,那么这个睡眠时间就很好(答案+1)

(醒来之后又要马上睡下一次的觉……)

问Vova该怎么安排这 n 次睡觉,才能使得好的睡眠时间次数最多

(即每次加上a[ i ]或a[ i ] - 1后的和对h取模,过程中会有多少次落在 l 与 r 之间)

 

解题思路:

动态规划,二维数组,一层记录第 i 次睡觉,另一层记录第 i 次睡醒的时间

dp[ i ] [ j ] 表示已经睡完 i 次觉,且第 i 次睡觉醒来的时间为 j 时,这个过程中答案的最大值

初始化数组为 -1 ,因为时间从 0 开始,所以特殊处理 dp[0][0] = 0

i = 1 ~ n      j = 0 ~ h-1

i 表示第 i 次睡觉,j 表示第 i 次开始睡时的时间

所以只要 dp[ i-1 ][ j ] != -1,就可以进行状态转移(因为等于 -1 相当于没有任何一个过程到达过时间 j )

假设这一次要睡 t 个单位时间

则状态转移方程为

  dp[i] [t] = max ( dp[i] [t] , dp[i-1] [j] + ( t >= l && t <= r ? 1 : 0 ) )

表示第 i 次醒来,醒来时间为 t 时的最大值,是由第 i 次睡觉,睡觉时间为 j 时的答案 与自身取大 转移而来

 

(46ms / 2000ms)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int dp[2050][2050];
 4 int main()
 5 {
 6     ios::sync_with_stdio(0);
 7     cin.tie(0);cout.tie(0);
 8     memset(dp,-1,sizeof dp);//初始时,没有访问过的时间设置为-1
 9     dp[0][0]=0;//如果某个时间有被访问过,那么dp就代表到达这个时间的这个过程中满足题意的最大个数
10     int n,h,l,r,i,j,a,t;
11     cin>>n>>h>>l>>r;
12     for(i=1;i<=n;i++)
13     {
14         cin>>a;
15         for(j=0;j<h;j++)//每种时间都考虑一遍
16         {
17             if(dp[i-1][j]!=-1)
18             {
19                 t=(j+a)%h;
20                 dp[i][t]=max(dp[i][t],dp[i-1][j]+(t>=l&&t<=r?1:0));//如果下一个位置满足条件,使dp+1
21                 t=(j+a-1+h)%h;//两种情况都在第i次进行考虑
22                 dp[i][t]=max(dp[i][t],dp[i-1][j]+(t>=l&&t<=r?1:0));
23             }
24         }
25     }
26     int ans=dp[n][0];
27     for(i=1;i<h;i++)
28         ans=max(ans,dp[n][i]);//在最后一次结束后所在的时间中寻找最大值
29     cout<<ans<<'\n';
30     
31     return 0;
32 }

 

猜你喜欢

转载自www.cnblogs.com/stelayuri/p/12508208.html