标签:div for 过程 cin 次数 ace 没有 turn strong
题意:
这个地方一天有 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 }
Codeforces 1324E - Sleeping Schedule
标签:div for 过程 cin 次数 ace 没有 turn strong
原文地址:https://www.cnblogs.com/stelayuri/p/12508208.html