再谈活动选择问题——论动态规划与贪心策略间的转化

前言:

学了这么长时间终于可以写一些自己想写的东西了(。・ω・)ノ゙

题目大意:

在给定的一些线段中,最多能选出多少条互不相交的线段

这是一道贪心基础题,相信大家都做过,我就不再具体阐述了

背景:

长久以来我一直以为活动分配问题应该用DP+树状数组O(nlogn)来解,但是经过xxq的提醒发现哦原来还有个O(n)的贪心做法(不算排序的时间,因为排序过程本身与决策无关),而且在内网里这道例题我本来是rk1的……然后发现自己真是沙茶,学了这么久反而用高端方法去做简单题,那我这不白学了吗TAT

但是……明明我这个DP推得没有什么问题,凭什么就比贪心慢呢?

百思不得其解,于是我就试图从《算法导论》中寻找答案,这篇文章先不谈子集系统拟阵最大权森林,然而书中思路来源全靠开脑洞,证明过程倒不是很复杂,但是“贪心算法在每一步选择当前看来最好的选择”说起来倒是简单,可谁也不能保证自己上考场的时候还能灵光一现地说哎我感觉这个DP好像可以搞成贪心,所以我们需要一种比较稳的寻找正确贪心策略的方法

经过了几天的思考我发现普通做法的时间复杂度之所以多一个log是因为记录了不必要的时域信息(当然,多记录一些信息也有好处,但是在本文中不详细讨论),而我们最终要求的结果只和频域的值有关,所以我们可以把时域和频域反过来维护(事实上贪心策略也是这么做的,只不过比较隐晦),这样我们就可以形式化地证明贪心策略的正确性了

下面请看我化腐朽DP为神奇贪心☆

很容易想到的一种DP方程:f[e[i].r]=max{f[j]}+1 (j<e[i].l)

经过上述分析我们把时域和频域反过来维护写出另一种DP方程:g[i+1]=e[j].r (g[i]<e[j].l),注意这里g同时有多个取值

然后由于问题要求尽可能地使g[i]<e[j].l成立,我们就只选取g最小的那个值,所以改写成g[i+1]=min{e[j].r} (g[i]<e[j].l)

形式看起来和一开始的那个方程还挺对称的

很明显这个方程本身就是一个贪心策略,g[i+1]从且仅从g[i]这个状态以一种方式转移而来

换句通俗的话具体地讲这个转移过程就是,每次新加进来一个活动的时候总是要选择结束时间最早的那个活动(真是一个熟悉的结论)

猜想:

可以出一道神题让右面的条件式是一个二次函数什么的,这样大家就不能靠感觉做题了(逃)

转载于:https://www.cnblogs.com/algonote/p/7678701.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值