通关【算法赛】
https://www.lanqiao.cn/problems/5889/learning/?contest_id=145
小蓝最近迷上了一款电玩游戏“蓝桥争霸”。这款游戏由很多关卡和副本组成,每一关可以抽象为一个节点,整个游戏的关卡可以抽象为一棵树形图,每一关会有一道算法题,只有当经验值不低于第 i 关的要求 ki 时,小蓝才能挑战成功通过此关,并且获得 si 的经验值,每关的经验值只能获得一次。每个关卡(除了 11 号点),都会有一个前置关卡,只有通过了前置关卡,才能挑战后续关卡。
小蓝初始在 11 号点,也就是游戏开局初始点,同时具有一个初始经验值 P,他可以任意规划挑战顺序,他想问你最多能够挑战成功多少道题。
小蓝会告诉你关卡的所有信息,以及他的初始经验值,你需要回答他最多能够挑战成功多少关卡。
第一行输入两个整数 n,P,表示关卡的数量以及小蓝的初始经验值。
接下来 n 行,每行输入三个整数 fi,si,ki,fi 表示每一关的前置关卡( f1 一定为 00 ),si 表示经验值,ki 表示挑战成功最少需要的经验值。
一个整数,表示在最优的规划下,最多能挑战成功的关卡数量。
- 4 5
- 0 3 5
- 1 2 8
- 1 3 9
- 3 1 15
3
游戏地图如下:

小蓝初始点在 11 号关卡,初始经验为 55。每个关卡具有挑战前提:11 号关卡可以直接挑战,如果要挑战 22 号关卡,必须通过 11 号关卡,3,43,4号关卡类似。
小蓝的一种挑战顺序如下:
由于初始经验为 55,满足 11 号关卡要求,所以可以直接挑战成功 11 号关卡,获得 33 经验值,此时经验值为 88,并且获得挑战 2,32,3 号关卡的机会。
此时经验为 88,满足 22 号关卡要求,但是不满足 33 号要求,所以可以直接挑战成功 22 号关卡,获得 22 经验值,此时经验值为 1010。
此时经验为 1010,满足 33 号关卡要求,所以对 33 号关卡挑战成功,获得 33 经验值,此时经验值为 1313,并且获得挑战 44 号关卡的机会。
此时经验为 1313,小于 44 号关卡要求,所以无法成功挑战 44 号关卡,游戏无法继续。
f1=0 数据保证输入为一棵树,并且根节点为 11。 首先,定义了一些全局变量和类型别名: 接下来是 使用了优先队列(最小堆)来实现任务调度。通过不断执行优先级最高的任务,并更新能量值,直到能量值不足以执行下一个任务为止。最终输出完成的任务数量。 O(n^2) 时间复杂度: 总结,整个算法的时间复杂度在最坏情况下为 O(n^2),但在实际情况下可能会更好。 O(n) 空间复杂度: 总结,整个算法的空间复杂度为 O(n),其中 n 是任务数量。 1. pair: Pair 基础 2. 优先队列 小顶堆 堆 的介绍 建议选着来看,看看大小堆是啥有啥用,就行了。 建议跳看 3.扩展 大顶堆 大顶堆可以通过使用 在 C++ 中, 4.再解释一下内容 觉得有用的话可以点点赞,支持一下。 如果愿意的话关注一下。会对你有更多的帮助。 每天都会不定时更新哦 >人< 。运行限制
语言 最大运行时间 最大运行内存 C++ 1s 256M C 1s 256M Java 2s 256M Python3 3s 256M PyPy3 3s 256M 思路和解题方法
N 定义为 1e5+100,表示任务数量的上限。Pair 是一个包含两个整数的类型别名,用于存储任务的优先级和任务编号。G 是一个邻接表,用于存储任务关系图,每个任务的子任务列表存储在 G 中。S 数组用于存储每个任务的耗能值。K 数组用于存储每个任务的优先级。n 表示任务数量。P 表示初始能量值。cnt、vis 是辅助变量。sol 函数,用于解决任务调度问题。函数的主要逻辑如下:n 和初始能量值 P。f、耗能值 S[i] 和优先级 K[i],并将每个任务添加到对应父任务的子任务列表中。q,用于存储任务的优先级和任务编号,按照优先级从小到大排序。ccnt 为 -1,因为初始任务不计入完成数量。ccnt 加一。ccnt。
复杂度
时间复杂度:
q 的时间复杂度为 O(nlogn),其中 n 是任务数量。 空间复杂度:
G 的空间复杂度为 O(n),存储了任务之间的关系。S 和 K 的空间复杂度为 O(n),存储了每个任务的耗能值和优先级。q 的空间复杂度为 O(n),存储了任务的优先级和任务编号。
c++ 代码
相关知识 和推荐视频
pair 是 C++ 标准库中的一个模板类,用于存储两个值的有序对。它定义在 头文件中。pair 类模板接受两个类型参数,分别表示第一个值的类型和第二个值的类型。例如,pair 表示一个包含一个整数和一个浮点数的有序对。pair 类模板的实例可以通过花括号 {} 初始化,也可以通过构造函数进行初始化。可以使用 first 和 second 成员变量来访问有序对中的第一个值和第二个值。 priority_queue
priority_queue 是 C++ 标准库中的一个模板类,用于实现优先队列(堆)。它定义在 头文件中。priority_queue 类模板接受三个类型参数,分别表示存储在队列中的元素类型、底层容器类型和比较函数对象类型。例如,priority_queue 表示一个存储整数的优先队列,使用 vector 作为底层容器,并按照从小到大的顺序进行排序。Pair 是一个包含两个整数的类型别名,vector 表示使用 vector 作为底层容器来存储 Pair 类型的元素,greater 表示使用 greater 函数对象来定义元素之间的比较关系。greater 是一个函数对象,它定义了对 Pair 类型的元素进行比较的方式。在这里,greater 使用 operator() 函数重载来比较两个 Pair 类型的元素,根据 Pair 中第一个值的大小进行比较。因此,priority_queue 创建的优先队列会按照 Pair 中第一个值的从小到大的顺序进行排序。
less 函数对象来定义元素之间的比较关系。priority_queue 默认使用 less 函数对象来实现大顶堆。
while (!q.empty()):当任务队列不为空时,执行循环体内的代码。if (P >= q.top().first):判断当前能量值 P 是否大于等于队首任务的优先级 q.top().first。如果是,则执行任务;否则,跳出循环。ccnt++:完成任务数量加一。Pair tmp = q.top():取出队首任务,并将其存储在临时变量 tmp 中。q.pop():弹出队首任务,将其移出任务队列。P += S[tmp.second]:将任务的能量值 S[tmp.second] 加到当前能量值 P 上,表示执行任务消耗了一定的能量。for (int v : G[tmp.second]):遍历该任务的子任务,使用范围-based for 循环,将每个子任务的编号存储在变量 v 中。q.push({K[v], v}):将子任务的优先级 K[v] 和编号 v 加入任务队列 q 中,表示将子任务加入待执行的任务队列中。else:当当前能量值不足以执行队首任务时,跳出循环。