动态规划-带权活动选择问题

问题描述

问题情景:在活动选择问题的基础上,为每个活动增加了权重。问题变为,一天中给定一系列活动,每个活动有一个权重。参加的活动必须是不相容的(incompatible),即在时间上不能有重叠。问如何安排一天的时间,使得参加的活动的权重和最大?

形式化定义:给定一个向量的集合 A = { a 1 ( s 1 , f 1 , w 1 ) , a 2 ( s 2 , f 2 , w 2 ) , . . . , a n ( s n , f n , w n ) } A=\{a_1(s_1,f_1, w_1),a_2(s_2,f_2,w_2),...,a_n(s_n,f_n,w_n)\} A={a1(s1,f1,w1),a2(s2,f2,w2),...,an(sn,fn,wn)},选择 A A A的子集 S S S,满足:
s i ≤ f j ∨ f i ≥ s j , ∀ a i , a j ∈ S s_i\leq f_j \lor f_i\geq s_j,\forall a_i,a_j\in S sifjfisjai,ajS
使最大化:
∑ a i ∈ S w i \sum\limits_{a_i\in S}w_i aiSwi

贪心算法

活动选择问题存在三种贪心思想:

  • 贪心策略一:优先参加时间最短的活动
  • 贪心策略二:优先参加最早开始的活动
  • 贪心策略三:优先参加最早结束的活动

在不带权的活动选择问题中,我们按优先参加最早结束的活动来进行贪心,并证明了方案的最优性。但在带权活动选择问题中,我们需要引入动态规划思想进行一些改进。

动态规划

i i i个不冲突活动的最大权重和”可以由以下两种情况得来:

  • 选择第 i i i个活动,则 i i i个不冲突活动的最大权重和 = 前 f ( i ) f(i) f(i)个不冲突活动的最大权重 + w i w_i wi
    • 其中 f ( i ) f(i) f(i)为选择 i i i之后在 i i i之前最后一个不与 i i i冲突的活动序号
  • 不选择第 i i i个活动,则 i i i个不冲突活动的最大权重和 = 前 i − 1 i-1 i1个不冲突活动的最大权重。

i i i个不冲突活动的最大权重和为 d p [ i ] dp[i] dp[i],则状态转移方程为:
d p [ i ] = m a x { d p [ i − 1 ] , d p [ f ( i ) ] } dp[i]=max\{dp[i-1], dp[f(i)]\} dp[i]=max{dp[i1],dp[f(i)]}

动态规划的复杂度为线性 O ( n ) O(n) O(n),而事先对活动排序的时间复杂度至少为 O ( n l o g n ) O(nlogn) O(nlogn)。因此整个算法的复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

例子:

在这里插入图片描述
对于上述问题,填表如下:

0123456791011
058812121213202021

因此最大权值和为21。

讨论:活动排序策略

一个值得讨论的问题是,当我们在动态规划中比较两个活动的“先后”时,采用的是什么标准?在前文的动态规划中,我们沿用不带权活动选择问题的做法,使用的是结束时间进行升序排序。那么,能否选择另外两种贪心思想来排序呢?

对于最早开始优先的思想,按开始时间进行排序,显然也是可行的。这需要进行一个反序的动态规划,相当于将活动图左右翻转了一下。

对于时间最短优先的思想,则很难进行动态规划,因为动态规划最主要是利用好递归的子问题,而按时间最短优先则会选择到在中间的活动,破坏了时间的连续性,从而无法形成子问题。

附:贪心算法和动态规划算法的比较

  • 贪心算法:一步步地通过增加子问题的规模来构造问题的解,并短视地(myopically)注重于当前构造当前的子问题:既不保存过去的子问题信息,也不关注更大规模的问题。
    • 如果贪心算法被证明能得到最优解的话,那么它一定是高效的好算法。
  • 动态规划:将问题分解为许多重叠的子问题,并通过填表将子问题的最优解合并为所求的最优解。
    • 动态规划的适用范围比贪心算法的范围更广。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值