CF-Round#627-div3-E题

CF-Round#627-div3-E题

E - Sleeping Schedule

传送门

本题是standard dynamic programming.
标准dp

题目给出主人公认为可以是“好眠”的时间段,一天的时间范围,睡觉的次数。然后一组序列。代表过多少小时入睡。主人公唯一可以选择的是他可以在所给的序列中原来的元素或者原来的元素-1之后的时间入睡。问这个主人公最多有多少个“好眠”次数。

dp~很明显啦
设定dp[i][j]代表第i次睡觉j时间的当前的“好眠”次数。
很显然初始化
dp[0][0] = 0;
然后因为求最大值。所以其他的dp值初始化为-1,我昨天没有测试。cf那个时候在system test。是我初始化为负无穷的时候没注意边界,还是老实点取一个老实的数据,就是-1取不到。就取它。

状态转移方程:
两种选择。要么选择a[i]之后时间入睡。要么选择a[i]-1之后时间入睡。
获取最大值。
因为不知道当前时间之前选择了几次a[i]时间,几次a[i] - 1时间
所以需要遍历一遍时间段。从一天开始到一天结束。
(j + a[i]) % h代表选择a[i]之后时间入睡
(j + a[i] - 1) % h代表选择a[i] - 1之后时间入睡
判断一下这个时间段是否满足“好眠”时间段的要求。满足的话,就拿前一次的j开始的时间dp+1即可
如果两次时间都不满足,维护最大值就行了
然后最后维护最后一次睡觉一天时间内最大值就可以啦

代码部分:

#include <bits/stdc++.h>
#define mst(a, n) memset(a, n, sizeof(a))
using namespace std;
const int N = 2e3 + 10;
const int INF = 1e9;
 
int dp[N][N];
int a[N];
int n, h, l, r;
 
int main()
{
	cin >> n >> h >> l >> r;
	for (int i = 1 ; i <= n; i++)
	{
		cin >> a[i];
	}
	mst(dp, -1);
	dp[0][0] = 0;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 0; j < h; j++)
		{
			if (dp[i - 1][j] >= 0)
			{
				int t = (j + a[i]) % h;
				dp[i][t] = max(dp[i][t], dp[i - 1][j] + (t >= l && t <= r));
				t = (j + a[i] - 1) % h;
				dp[i][t] = max(dp[i][t], dp[i - 1][j] + (t >= l && t <= r));
			}
		}
	}
	int ans = 0;
	for (int i = 0; i < h; i++)
	{
		ans = max(ans, dp[n][i]);
	}
	cout << ans << endl;
	return 0;
}
发布了112 篇原创文章 · 获赞 3 · 访问量 2651

猜你喜欢

转载自blog.csdn.net/qq_44624316/article/details/104846936