今天来给大家讲守望者的逃离这道题
先上题目
题目描述
恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变。守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去。到那时,岛上的所有人都会遇难。守望者的跑步速度为17m/s,以这样的速度是无法逃离岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s,只有处在 原地休息状态时才能恢复。
现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的任务写写一个程序帮助守望者计算如何在最短的时 间内逃离荒岛,若不能逃出,则输出守望者在剩下的时间能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位,且每次活动的持续时间为整数秒。距离的单位为米(m)。
输入格式
一行,包括三个数据
m<=1000,s<=m<=1000,s<=m<=1000,s<= 108,T<=3000000T<=3000000T<=3000000
输出格式
第1行为字符串"Yes"或"No" (区分大小写),即守望者是否能逃离荒岛。
第2行包含一个整数,第一行为"Yes" (区分大小写)时表示守望着逃离荒岛的最短时间
第1行为"No" (区分大小写) 时表示守望者能走的最远距离。
样例
样例输入
39 200 4
样例输出
No
197
思路
这道题有两种思路 一种是动态规划 一种则是贪心 今天给大家讲运用动态规划该怎么做
我们先定义状态
设dp[i]dp[i]dp[i]表示 在第iii秒钟可以到达的最远距离
接下来就是状态转移方程
我们用两个循环 一个用来枚举只用魔法值的情况 另一个就是在来看使用魔法值跑的远 还是直接跑步跑的远
在第一个循环中 我们设当前还剩的魔法值为m
则按照原则 如果m>=10m>=10m>=10 dp[i]=dp[i−1]+60dp[i]=dp[i-1]+60dp[i]=dp[i−1]+60 然后再将mmm减10
如果m<10m<10m<10 dp[i]=dp[i−1]dp[i]=dp[i-1]dp[i]=dp[i−1] 然后再将mmm加上4
在第二个循环中 很显然我们只需要将当前最优解与上一时刻加上跑步的速度去一个maxmaxmax即可 所以第二个循环的状态转移方程为dp[i]=max(dp[i],dp[i−1]+17)dp[i]=max(dp[i],dp[i-1]+17)dp[i]=max(dp[i],dp[i−1]+17)
如果dp[T]<sdp[T]<sdp[T]<s 即走了TTT秒钟一逃不出来 我们就直接输出最远距离 也就是dp[T]dp[T]dp[T]
其他情况 我们就将dpdpdp数组从T一直遍历到0当我们找到最后一个大于sss的dp[i]dp[i]dp[i]时 我们就直接输出iii
代码
#include<bits/stdc++.h>
using namespace std;
long long dp[1000005];
int n,m,t;
int main()
{
cin>>n>>m>>t;
for(int i=1;i<=t;++i)//第一层循环
{
if(n>=10)//如果当前魔法值大于十
{
dp[i]=dp[i-1]+60;//dp[i]=dp[i-1]+60
n-=10;//将魔法值减10
}
else//如果小于10 就停留
{
dp[i]=dp[i-1];//距离不会增加 直接等与上一时刻的距离
n+=4;//停留一次 魔法值加上4
}
}
for(int i=1;i<=t;++i)
{
dp[i]=max(dp[i],dp[i-1]+17);//记得看跑步的情况 取一个max
}
if(dp[t]<m)
{
cout<<"No"<<endl;//最大距离小于S时 输出no
cout<<dp[t]<<endl;//输出到达的最晚距离
}
else
{
for(int i=t;i>=0;i--)
{
if(dp[i]<m)
{
cout<<"Yes"<<endl;//大于S时 输出Yes
cout<<i+1<<endl;//由于这是第一个小于S的数 所以输出上一个 也就是i+1
return 0;
}
}
}
}