P1095 守望者的逃离(C++_贪心_模拟/dp)

题目描述

恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变。守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去。到那时,岛上的所有人都会遇难。守望者的跑步速度为17m/s,以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s,只有处在原地休息状态时才能恢复。

现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的任务是写一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的时间内能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位,且每次活动的持续时间为整数秒。距离的单位为米(m)。

输入格式

共一行,包括空格隔开的三个非负整数M,S,T。

输出格式

共两行。

第1行为字符串“Yes”或“No”(区分大小写),即守望者是否能逃离荒岛。

第2行包含一个整数。第一行为“Yes”(区分大小写)时表示守望者逃离荒岛的最短时间;第一行为“No”(区分大小写)时表示守望者能走的最远距离。

输入输出样例

输入 #1

39 200 4

输出 #1

No
197

输入 #2

36 255 10

输出 #2

Yes
6

说明/提示

30%的数据满足: 1 ≤ T ≤ 10 , 1 ≤ S ≤ 100 1 \le T \le 10, 1 \le S \le 100 1T10,1S100

50%的数据满足: 1 ≤ T < ≤ 1000 , 1 ≤ S ≤ 10000 1 \le T < \le 1000, 1 \le S \le 10000 1T<1000,1S10000

100%的数据满足: 1 ≤ T ≤ 300000 , 0 ≤ M ≤ 1000 , 1 ≤ S ≤ 1 0 8 1 \le T \le 300000,0 \le M \le 1000, 1 \le S \le 10^8 1T300000,0M1000,1S108.

思路

第一段模拟的思路应该在代码的注释中写的很清楚了,有点写复杂了,应该一个dp就可以结束的!!!!!!!!!第二段代码是dp。

Code1

(贪心+模拟)
#include
using namespace std;
int main()
{
	int m, s, t, flag = 0;//m初始魔法, s距离出口的距离, t剩余时间
	cin >> m >> s >> t;
	int S = s, T = t;
	float temp;
	if (s == 0)
		flag = 1;
	while (t > 0 && (m >= 10 || (ceil((10 - m) / 4.0) + 1 <= t) && s > ((ceil((10 - m) / 4.0) + 1) * 17))){//(剩余魔法值还可以支持闪现)或者(剩余时间内还可以攒闪现并且有1s的时间可以闪出去而且还要比跑着用时更短)
		if (m < 10){//魔法值余量不足
			t -= (ceil((10 - m) / 4.0) + 1);//减去原地不动的时间和闪现的一秒
			m += (ceil((10 - m) / 4.0) * 4 - 10);//原来的魔法值加上攒出的魔法值减去闪现需要消耗的魔法值
		}
		else{
			t -= 1;//时间减去一秒闪现的时间
			m -= 10;//魔法值减去一次闪现的魔法值
		}
		s -= 60;//距离缩短一个闪现的距离
		if (s <= 0){//闪现过头了,说明ok
			flag = 1;
			break;
		}
	}
	if (flag == 0)//只靠闪现不足以出去或者不是最优
		while (t--){//剩余的时间内全部跑步
			s -= 17;
			if (s <= 0){
				flag = 1;
				break;
			}
		}
	if (flag == 1)
		cout << "Yes" << endl << T - t;
	else
		cout << "No" << endl << S - s;
	return 0;
}

Code2

(贪心+dp)
#include
using namespace std;
int dp[300010];
int main()
{
	int m, s, t;
	cin >> m >> s >> t;
	for (int i = 1; i <= t; i++)//闪现
		if (m >= 10)
		{
			dp[i] = dp[i - 1] + 60;
			m -= 10;
		}
		else
		{
			dp[i] = dp[i - 1];
			m += 4;
		}
	for (int i = 1; i <= t; i++)//跑步
	{
		dp[i] = max(dp[i], dp[i - 1] + 17);
		if (dp[i] >= s)
		{
			cout << "Yes" << endl << i;
			return 0;
		}
	}
	cout << "No" << endl <<dp[t];
	return 0;
}

你可能感兴趣的:(算法)