CodeForces 1384B2. Koa and the Beach (Hard Version)(贪心)

题意:沙滩从左往右由海岸线,n米的海和一个在n+1的点的岛组成。一个人测量了从海岸线(1,2,dots,n)米到岛屿的海的深度,并保存在(d)数组中,这个海有潮汐,潮汐的强度取决于参数(k),参数(k)影响了海的深度,对于从时间(t = 0)开始,先k秒,每一秒,潮汐导致所有的深度+1,然后再k秒,潮汐每秒导致所有的深度都减1。这个过程不断地持续着,例如对于索引从0开始的数组(p = [0, 1, 2,...,k - 2, k - 1, k, k - 1, k - 2, ..., 2, 1]),长度为2k,在时间t,第i米的深度为(di+p[t\,mod\,k])。这个人从海岸线开始游到岛屿,每一秒,他可以前进或者呆在原地,时间t + 1,这个人有一个被淹死的水的深度的参数(l),如果(当且深度>l),那么这个人就会被淹死。求是否存在一种游的方式,使得这个人可以游到岛屿。

分析:贪心做法,我们考虑两个完全安全的点的状态,什么是完全安全的点呢?比如dep[i] + k <= l,就是加上潮汐的最大增量也不会超过淹死的深度的点。考虑两个完全安全点之间的点,我们思考什么样的贪心决策最好。从一个完全安全点开始,我们不错的决策是,等到潮汐上涨到最大的时候,我们才往之后的点游下去,因为之后潮汐是随着时间下降的,如果接下来的点dep[i] + tide > l的话,即加上这个随时间下降的潮汐的值都大于l的话,那么我们就没有办法,只能再等一会时间,要等多久呢,即diff = dep[i] + tide - l,相应的潮汐的下降值,tide - diff,如果tide - diff < 0,说明没有更优的方案游了,否则让tide变成tide - diff。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
const int N = 300005;
int d[N];
int main()
{
	int t;
	scanf("%d", &t);

	while (t--)
	{
		int n, k, l;
		scanf("%d%d%d", &n, &k, &l);

		for (int i = 1; i <= n; ++i)
		{
			scanf("%d", &d[i]);
		}

		vector<int> v;
		v.push_back(0);

		for (int i = 1; i <= n; ++i)
		{
			if (d[i] + k <= l) v.push_back(i);
		}

		v.push_back(n + 1);

		bool flag = true;
		for (int i = 1; i < v.size(); ++i)
		{
			bool down = true;
			int tide = k;
			//两个完全的安全点之间的点
			for (int j = v[i - 1] + 1; j < v[i]; ++j)
			{
				//潮汐加上随时间变换的量
				tide += down ? -1 : 1;

				if (down)
				{
					//深度值加上潮汐增量都大于l的话,我们要等一会,让潮汐再降一些
					if (d[j] + tide > l)
					{
						int diff = d[j] + tide - l;
						tide -= diff;
					}
				}
				if (tide < 0 || d[j] + tide > l)
				{
					flag = false;
					break;
				}
				if (tide == 0)
				{
					down = false;
				}
			}
			if (!flag) break;
		}

		if (flag)
		{
			puts("Yes");
		}
		else
		{
			puts("No");
		}

	}
	


	return 0;
}
原文地址:https://www.cnblogs.com/pixel-Teee/p/13386351.html