计蒜客 - 守望者的逃离

时间限制 1000ms 空间限制 65536K

题目描述

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

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

输入格式

输入仅一行,包括空格隔开的三个非负整数 M,S,T(0<=M<=1e3,1<=S<=1e8,1<=T<=3e5)

输出格式

输出包含两行。

 1 行为字符串YesNo,即守望者是否能逃离荒岛。

 2 行包含一个整数。

第一行为Yes时表示守望着逃离荒岛的最短时间

第一行为No时表示守望者能走的最远距离。

样例输入

39 200 4

样例输出

No
197

【思路】

    个人感觉这道题贪心能做但是要考虑的情况实在太多所以就看了下动态规划的算法,直接开dp数组肯定会MLE的,所以这里的状态转移方程的确立很关键,我没有想出来,也是理解别人的思路。设dp1[t]是守望者在用t(s)能达到的最大距离,dp2[t]是守望者在只能用闪烁技能的情况下用t(s)能达到的最大距离,那么状态转移方程就是dp1[t]=max(dp1[t-1]+17,dp2[t]),不难理解,但就是想不到,233。

#include
#include
#include
#include
using namespace std;

const int maxt = 3e5 + 500;

int m, s, t;
int dp1[maxt], dp2[maxt];

int main() {
	int i;
	while (scanf("%d%d%d", &m, &s, &t) == 3) {
		dp1[0] = dp2[0] = 0;
		for (i = 1; i <= t; i++) {
			if (m >= 10) {//蓝够就闪烁
				dp2[i] = dp2[i - 1] + 60;
				m -= 10;
			}
			else {//蓝不够对dp2只能回蓝,不能移动
				m += 4;
				dp2[i] = dp2[i - 1];
			}
			dp1[i] = max(dp1[i - 1] + 17, dp2[i]);//根据状态转移递推结果
			if (dp1[i] >= s) break;
		}
		if (i <= t) {
			printf("Yes\n%d\n", i);
		}
		else {
			printf("No\n%d\n", dp1[t]);
		}
	}
	return 0;
}


你可能感兴趣的:(动态规划-----线性DP)