发布时间:2026/9/6 14:57:46
试解2014ACM大赛赛题守望者逃离荒岛问题 题目如下恶魔猎手尤迫安野心勃勃.他背叛了暗夜精灵率深藏在海底的那加企图叛变守望者在与尤迪安的交锋中遭遇了围杀.被困在一个荒芜的大岛上。为了杀死守望者尤迪安开始对这个荒岛施咒这座岛很快就会沉下去到那时刀上的所有人都会遇难守望者的跑步速度为17m/s 以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术可在1s内移动60m不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s只有处在原地休息状态时才能恢复。现在已知守望者的魔法初值M他所在的初始位置与岛的出口之间的距离L岛沉没的时间T。你的任务是写一个程序帮助守望者计算如何在最短的时间内逃离荒岛若不能逃出则输出守望者在剩下的时间内能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位。且每次活动的持续时间为整数秒。距离的单位为米(m)。题解这道题很有意思仔细想想其实不难每单位时间守望者只能有三种动作施法瞬移原地休息和向前移动我们用1表示先前移动用2表示施法瞬移3表示原地休息。根据题意我们需要把沉没时间T划分为T等分[0 1],[12]……[T-1 T],并建立一个长度为T的双栈这里用第一维大小为T第二维大小为2的二维数组a[T][2]表示。a[i][0]代表i-i1时间段内守望者的动作可以为1,2或3,a[i][1],代表i时间点守望者的魔法值。按照一定规则利用栈逐层向下试探或向上回溯寻找守望者可以逃离荒岛的动作序列。如果试探到t时间点守望者移动的距离l大于等于L则守望者成功逃离荒岛此时双栈的左侧部分a[0][0]–a[t-1][0]就存放着逃离荒岛的动作序列,利用t通过min函数做相应的计算可以得到此时守望者逃离荒岛的时间用if语句进行简单的比较可以在试探结束时获得守望者逃离荒岛的最短时间。如果试探到T时间点守望者移动的距离l小于L此时守望者无法逃离荒岛而若此前一直没有试探到可行的动作序列就通过if语句进行简单的比较以确定无法逃离荒岛时能移动的最远距离(如果之后试探到了可行动作序列那么这种比较没有必要但由于无法事先获知可行动作序列的存在性所以这里只能进行比较)我在编写程序时添加了一个附加条件守望者的魔法初值M就是魔法上限以上是大致的思路下面是具体的代码实现(本题很自然的想法是用贪心算法求解但这里要求出所有解而贪心算法用于逼近和求取最优解所以这里没有采用贪心算法对本程序进行适当修改可得贪心算法的版本)#include stdio.h #define T 9 //荒岛沉没时间 #define M 12 //守望者魔法初值也为魔法上限 #define L 180 //初始位置和岛出口的距离 #define R 4 //魔法值恢复速度 #define Vf 17 //守望者跑步速度 #define Vs 60 //守望者施法瞬移速度 #define F 10 //施法消耗魔法值量 void move(int a[], int i, int* l, int* m); //在单位时间内移动守望者并记录守望者的状态变化 void fmove(int a[], int i, int* l, int* m); //回溯至上一个时间点的函数守望者状态还原至上一个时间点 float min(float* tmin, int t, int l, int a[], int i, int* sign); //函数计算守望者按已找到的可行动作序列逃离荒岛所需的时间 void output(int a[], int i, int count, float interval); //输出逃出方案 bool Try(int a[], int* fartest, float* tmin); //回溯试探函数判断有无逃出方案寻找逃出方案 int main() { int j; int fartest; //无法逃离荒岛能移动的最远距离 float tmin; //逃离荒岛最短时间 int a[T]; //用于回溯的栈 bool TF; //标志能否逃出荒岛 for (j 0; j T; j) //双栈初始化 { a[j] 0; } TF Try(a, fartest, tmin); //试探和回溯 if (TF) { printf(可以逃离荒岛\n); printf(逃离荒岛的最短时间:%f\n, tmin); } else { printf(无法逃离荒岛\n); printf(所能移动的最远距离:%d\n, fartest); } return 0; } bool Try(int a[], int* fartest, float* tmin) { float interval; int i, t, l, m; int flag, sign, count; t 1; //计时变量初始化 i 0; //初始化栈顶标志 flag 0; sign 0; count 0; l 0; m M; while (1) { if (i 0) { a[0]; //试探下一种动作 if (a[0] 3) { break; //试探完毕退出循环 } } else { if (a[i] 2) //当前时间段已无动作可供尝试回溯 { fmove(a, i, l, m); //回溯恢复守望者状态至前一时间点 a[i] 0; //本时间段动作清零 t--; i--; //向后回溯 continue; } if (a[i] ! 0) //回溯至本时间段后需要改变原有动作尝试下一个新动作 { fmove(a, i, l, m); //同上 } a[i]; //同上 } if (a[i] 1 F m) a[i]; //魔法值不够进行施法,考虑下一种动作 move(a, i, l, m); //移动守望者 if (l L) //找到可行动作序列 { count; //方案计数变量增一 interval min(tmin, t, l, a, i, sign); //计算当前可行逃出方案的逃出时间进行相应比较以确定最短逃出时间 output(a, i, count, interval); //输出可行逃出方案 } else { if (i 0 || i ! T - 1) { t; i; //向前试探 //当前时间点既未逃出荒岛时间也未用尽继续向前试探 } else { //逃离荒岛失败 if (sign 0) //之前没有找到可行动作序列 { if (flag 0) { *fartest l; flag 1; } //简单的比较,以找出不能逃离荒岛时可移动最远距离 else { if (l *fartest) *fartest l; } } } } } printf(总共有%d种逃出方案\n, count); //输出逃出方案总数 if (sign 1) return true; //返回标志是否可以逃离荒岛的布尔常量 else return false; } void move(int a[], int i, int* l, int* m) { if (a[i] 2) //按第一种动作移动时状态变化 { *l Vf *l; } else if (a[i] 1) //按第二种动作施法瞬移移动时状态变化 { *l Vs *l; *m *m - F; } else //按第三种动作原地休息时的状态变化 { if (*m R M) { *m *m R; } else { *m M; } } } void fmove(int a[], int i, int* l, int* m) { if (a[i] 2) //按向前移动还原状态 { *l *l - Vf; } else if (a[i] 1) //按施法瞬移还原状态 { *l *l - Vs; *m *m F; } else { *m *m - R; //按原地休息还原状态 } } float min(float* tmin, int t, int l, int a[], int i, int* sign) { if (l L) //时间点i正好已移动了距离L { if (*sign 0) { *sign 1; *tmin t; //逃离时间为t,比较确定最短逃离时间 } else { if (*tmin t) { *tmin t; } } return (float)t; //逃离时间就为t,返回 } else //时间点i移动距离超过L { int V; if (a[i] 2) { V Vf; } else { V Vs; } if (*sign 0) //按向前移动或施法瞬移计算真实的逃出荒岛时间 { *sign 1; *tmin t - (l - L) / (float)V; //作简单的比较确定最短逃离时间 } else { if (*tmin t - (l - L) / (float)V) { *tmin t - (l - L) / (float)V; } } return t - (l - L) / (float)V; //逃出荒岛时间为t-(l-L)/(float)V返回 } } void output(int a[], int i, int count, float interval) { int j; printf(第%d种逃出方案\n, count); for (j 0; j i; j) { printf(time%d to time%d\n, j - 1, j); if (a[j] 1) printf(施法瞬移\n); //逃出方案和逃出时间输出 else if (a[j] 2) printf(向前移动\n); else printf(原地休息\n); } printf(逃离荒岛所用时间:%f\n, interval); }

相关新闻

2026/9/6 14:52:46

红黑树详细分析与c++实现

红黑树的删除红黑树删除极其复杂,实现难度比AVL树删除更大,要考虑的各种分支情况繁多,编程实现时在琐碎的细节上容易出错,但只要用心,正确实现删除算法不难对红黑树按对二叉搜索树执行删除的方式执行删除,如果实际删除的节点是红节…

2026/9/6 14:52:46

Trie树的实现

Trie树是保存字符串公共前缀信息的数据结构,可用于字符串多模匹配&#xff0c;普通的非压缩Trie树实现如下第一种实现:每个分支节点使用map标准库容器保存前缀索引#include <map> #include <stack> #include <vector> #include <string> #include <…

2026/9/6 14:52:46

计算机图形学复习指南:从渲染管线到核心算法

简介&#xff1a;计算机图形学复习材料是一份面向计算机图形学课程复习备考的PDF资料&#xff0c;核心聚焦图形学定义、图形分类、图形与图像关系、应用领域、OpenGL体系、光栅扫描显示系统、帧缓冲存储器与计算机图形系统等考点。PDF文档按章节梳理了填空、简答、计算与算法描…

2026/9/6 15:47:57

Buzz离线语音转文字:免费本地转录,十分钟上手指南

Buzz离线语音转文字&#xff1a;免费本地转录&#xff0c;十分钟上手指南 【免费下载链接】buzz Buzz transcribes and translates audio offline on your personal computer. Powered by OpenAIs Whisper. 项目地址: https://gitcode.com/GitHub_Trending/buz/buzz 你手…

2026/9/6 0:06:59

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊&#xff01;#雷神 #复联”这类调侃式短标题&#xff0c;第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里&#xff0c;但细想一下就能发现&#xff0c;它真正碰到的根本不是…

2026/9/6 0:06:59

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊&#xff0c;可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”&#xff0c;你会发现&#xff0c;这场比较本质上是两个不同 IP 策略的长期结果对比&#xff1a;超人赢在定义了整个超级英雄题材…

2026/9/6 0:06:59

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介&#xff1a;本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案&#xff0c;聚焦调制信号自动检测与识别这一典型无线通信任务&#xff0c;解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件&#xff08;10.73MB&#xff09;&…

2026/9/6 0:06:59

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊&#xff01;#雷神 #复联”这类调侃式短标题&#xff0c;第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里&#xff0c;但细想一下就能发现&#xff0c;它真正碰到的根本不是…

2026/9/6 0:06:59

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊&#xff0c;可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”&#xff0c;你会发现&#xff0c;这场比较本质上是两个不同 IP 策略的长期结果对比&#xff1a;超人赢在定义了整个超级英雄题材…

2026/9/6 0:06:59

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介&#xff1a;本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案&#xff0c;聚焦调制信号自动检测与识别这一典型无线通信任务&#xff0c;解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件&#xff08;10.73MB&#xff09;&…

2026/9/6 11:40:10

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行&#xff0c;Type-C接口算是典型的“看着简单&#xff0c;做起来全坑”的东西。光引脚就24个&#xff0c;高低速信号、电源、控制线全部塞在一个小小的连接器里&#xff0c;如果PCB布局不做规划&#xff0c;打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/5 2:30:42

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/6 10:19:40

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…