[动态规划] 守望者的逃离

这篇博客介绍了如何使用动态规划解决一个游戏策略问题——守望者在即将沉没的岛屿上逃离。问题涉及到跑步、闪烁法术和魔法值管理。动态规划状态转移方程分为两部分,分别考虑使用和不使用闪烁法术的情况。通过遍历所有可能的策略,确定最短逃离时间和最远行走距离。当守望者无法逃离时,输出最远能达到的距离;否则,输出逃离的最短时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天来给大家讲守望者的逃离这道题

先上题目
题目描述
恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变。守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去。到那时,岛上的所有人都会遇难。守望者的跑步速度为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[i1]+60 然后再将mmm减10
如果m<10m<10m<10 dp[i]=dp[i−1]dp[i]=dp[i-1]dp[i]=dp[i1] 然后再将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[i1]+17)
如果dp[T]<sdp[T]<sdp[T]<s 即走了TTT秒钟一逃不出来 我们就直接输出最远距离 也就是dp[T]dp[T]dp[T]
其他情况 我们就将dpdpdp数组从T一直遍历到0当我们找到最后一个大于sssdp[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;
			}
		}
	}
} 
华丽结束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值