题目E
题意
每天有
h
h
h 个小时,定义一个
g
o
o
d
good
good 的概念:入睡时间在
[
l
,
r
]
[l,r]
[l,r] 范围内
(
0
≤
l
≤
r
<
h
)
(0≤l≤r<h)
(0≤l≤r<h)。
给出睡觉次数
n
n
n 和
n
n
n 个正整数
a
1
,
a
2
,
a
3
,
.
.
.
a
n
a_1,a_2,a_3,...a_n
a1,a2,a3,...an ,代表第
i
i
i 次睡觉需等待的时间,这个时间可以选择
a
i
a_i
ai 或
a
i
−
1
a_i-1
ai−1 。起始时间
t
=
0
t=0
t=0 。
现在针对以上输入,求出
n
n
n 次睡觉时间中尽可能多的满足
g
o
o
d
good
good的次数。
思路
我们要知道每次睡觉的时间是多少,判断在不在范围里。但是考虑
n
n
n 次选择的复杂性,每次都有两种情况,暴力解决时间复杂度很大,所以是动态规划的思路。
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示当第
i
i
i 次入睡时间是
j
j
j 时,此时
g
o
o
d
good
good 的最多次数。
下面讨论的时间都是对
h
h
h 取模后的时间,都在
[
0
,
h
)
[0,h)
[0,h) 。在第
i
i
i 次做选择时,对所有可能的入睡时间
t
i
t_i
ti 来说(对
t
i
t_i
ti 的取值进行遍历),上一次的入睡时间
t
t
t :
(
t
i
−
a
i
+
h
)
%
h
(t_i-a_i+h)\%h
(ti−ai+h)%h 或者
(
t
i
−
(
a
i
−
1
)
+
h
)
%
h
(t_i-(a_i-1)+h)\%h
(ti−(ai−1)+h)%h ,可以直接使用已知结果
d
p
[
i
−
1
]
[
t
]
dp[i-1][t]
dp[i−1][t] ,再加上对
t
i
t_i
ti 的判断。
复杂度是
O
(
n
∗
h
)
O(n*h)
O(n∗h) 。
代码
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 2020;
const int MAX_H = 2020;
int n,h,l,r;
int a[MAX_N];
int dp[MAX_N][MAX_H];
int ans;
int main(){
cin >> n >> h >> l >> r;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++){
for(int j=0;j<h;j++){
dp[i][j]=-MAX_N;
}
}
if(a[1]>=l&&a[1]<=r) dp[1][a[1]]=1;
else dp[1][a[1]]=0;
if(a[1]>=l+1&&a[1]<=r+1) dp[1][a[1]-1]=1;
else dp[1][a[1]-1]=0;
for(int i=2;i<=n;i++){
for(int j=0;j<h;j++){
int p=j-a[i];
int q=j-a[i]+1;
if(p<0) p+=h;
if(q<0) q+=h;
int d=0;
if(j>=l&&j<=r) d=1;
dp[i][j]=max(dp[i-1][p]+d,dp[i-1][q]+d);
}
}
for(int j=0;j<h;j++){
ans=max(ans,dp[n][j]);
}
cout << ans;
return 0;
}