本文主要以例题讲解和贪心方法入手。
邻项交换
当我们确定操作顺序,并按照题意模拟即可得出答案,就要用邻项交换的办法来确定最优的操作顺序。
对于一个排队顺序 T1∼Tn,答案显然等于:
∑ni=1(n−i)×Tin
那么将其中的 T2,T3 拎出来,将他们交换位置,显然不会影响后面的 T 的计算,而:
(n−1)×T2+(n−2)×T3
变成了:
(n−2)×T2+(n−1)×T3
那么如果想让交换前的更优,显然需要满足:
(n−1)×T2+(n−2)×T3<(n−2)×T2+(n−1)×T3
即:
T2<T3
所以我们要按照 T 从小到大的顺序进行排序。这样就能取得最优值。
同样,将排队顺序写出来后,即可按照题意模拟,将答案算出。
直接考虑第 i 个人的贡献:∏i−1j=1ljri,第 i+1 个人的贡献显然是 ∏ij=1ljri+1,那么交换后,变成 li+1×∏i−1j=1ljri 和 ∏i−1j=1ljri+1,要想交换前更优,显然应该满足:
max{∏i−1j=1ljri,∏ij=1ljri+1}<max{li+1×∏i−1j=1ljri,∏i−1j=1ljri+1}
可以转化为比较:
∏ij=1ljri+1<li+1×∏i−1j=1ljri
即:
liri+1<li+1ri
即:
li×ri<li+1×ri+1
按照这个式子排序即可。
先对问题进行简单的分析,如果我们将节点 k 的子儿子答案全部计算出来(记作 ansi,并设权值为 vi),并且将进入儿子的顺序确定下来,那么答案就是:
max{vk+v1+v2+...+vsiz(son),ans1,v1+ans2,vk+v1+v2+ans3...}
同样,我们取其中的两个 vk+∑i−1j=1vj+ansi 和 vk+∑ij=1vj+ansi+1,交换后:vk+∑i−1j=1vj+ansi+1 和 vk+∑i−1j=1vj+ansi+vi+1,那么我们只需要比较:
vk+i∑j=1vj+ansi+1<vk+i−1∑j=1vj+ansi+vi+1
即可,就是满足:
vi−ansi<vi+1−ansi+1
处理所有节点时,按照这个排序即可。
一开始想了一个很离谱的贪心策略:对于目前所有可以做的任务,选择其中 b 最大的来做。但这样显然不对,比如:
就能将其卡掉,原因是先做 9 -5
再做 4 -2
可以做完,但是先做 4 -2
会导致 9
做不了。
从另外一个角度考虑:对于 b>0 的,先将其做了显然最优,接着考虑 b<0 的,考虑两个事件 t1,b1 和 t2,b2,什么情况下使得先做 1 后做 2 可以,先做 2 后做 1 不行。
可以列出如下方程:
⎧⎪
⎪⎨⎪
⎪⎩T>t1T+b1>t2T>t2T+b2≤t1
有不等式相关性质不难得到:
t1+b1>t2+b2
所以按照 t+b 的值排序从大到小排序即可。
总结:“留后路”的前提是不会使得原来能做的事情变得不能做,所以凡是对于这种确定顺序模拟的题目,我们都可以使用邻项交换的方法进行分析。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效