目录
问题描述
情景:假如你去逛公园,买了一张通票,公园在不同时段有不同的活动(时间段可能有重叠),如果参加一个活动,就必须参加完整个过程,也不能分身同时参加多个活动,请问你怎么安排一天的时间,以参加尽可能多的活动?
形式化定义:给定一个向量的集合
A
=
{
a
1
(
s
1
,
f
1
)
,
a
2
(
s
2
,
f
2
)
,
.
.
.
,
a
n
(
s
n
,
f
n
)
}
A=\{a_1(s_1,f_1),a_2(s_2,f_2),...,a_n(s_n,f_n)\}
A={a1(s1,f1),a2(s2,f2),...,an(sn,fn)},选择
A
A
A的子集
S
S
S,满足:
s
i
≤
f
j
∨
f
i
≥
s
j
,
∀
1
≤
i
,
j
≤
n
s_i\leq f_j \lor f_i\geq s_j,\forall 1\leq i,j\leq n
si≤fj∨fi≥sj,∀1≤i,j≤n
使最大化:
c
a
r
d
(
S
)
card(S)
card(S)
贪心算法
在这个问题上,至少可以列出以下三种贪心策略,但只有策略三是能得到最优解的。
贪心策略一:优先参加时间最短的活动
时间最短的活动并不一定是最优的,因为一个时间最短的活动可能会破坏掉原本可以参加的两个活动,如下图所示:
贪心策略二:优先参加最早开始的活动
最早开始的活动显然不是最优的,一个反例如下图所示:
贪心策略三:优先参加最早结束的活动
这种贪心策略指导的算法如下:
- Step1:选择最结束时间早的活动
- Step2:删除与已选择活动不相容(举办时间有重叠)的活动
- Step3:在剩余可选择活动中重复Step1和Step2,直到不剩没有选择的不相容活动。最后剩下的子集就是所求的解。
可以证明,这种贪心策略能够得出最优解。
策略三的正确性证明
我们仍然采用交换验证法来证明,任意最优解都可以等优越性地转化为我们的贪心算法所求的解,如果它们不是原本就相同的话。
记贪心算法所求得的解为 G = < x 1 , x 2 , . . . , x p > G=<x_1,x_2,...,x_p> G=<x1,x2,...,xp>,而任意最优解为 O = < y 1 , y 2 , . . . , y q > O=<y_1,y_2,...,y_q> O=<y1,y2,...,yq>。由于 O O O是最优解,一定有 p ≤ q p\leq q p≤q。
从下标为 1 1 1开始比较,假设第一个不同的活动为 x i ≠ y i x_i\neq y_i xi=yi,那么一定有 s x i ≥ f x i − 1 s_{x_{i}}\geq f_{x_{i-1}} sxi≥fxi−1, s y i ≥ f y i − 1 = f x i − 1 s_{y_{i}}\geq f_{y_{i-1}}=f_{x_{i-1}} syi≥fyi−1=fxi−1。又因为贪心算法总是选择结束时间最早的活动,有 f x i ≤ f y i f_{x_i}\leq f_{y_i} fxi≤fyi。因此,方案 O O O可以不选择 y i y_i yi活动而选择 x i x_i xi活动,且保持一天参加活动数不变。
重复以上动作,可以使 O O O的前 p p p个活动与 G G G的 p p p个活动相同。由于 x p x_p xp之后已经安排不下任何活动了,转化后的 O O O也只有 p p p个活动(或者说转化前就一定有 p = q p=q p=q)。这样,最优解 O O O就被转化为了我们贪心算法的解 G G G。贪心算法的正确性得证。
讨论
最早开始优先的贪心策略能有多差?
最极端的案例是一个活动从早办到晚,而稍晚一点的一系列活动每个都很短,按最早开始优先的贪心策略就只能参加一个活动。也就是说,这种贪心算法的结果可以任意差,即 O P T A = ∞ \frac{OPT}{A}=\infin AOPT=∞。
最短时间优先策略能有多差?
前面说过,这种方案并不一定是最优解,但可以证明,它也不是任意差,事实上有 O P T A ≤ 2 \frac{OPT}{A}\leq 2 AOPT≤2。
证明:
前面说过,一个时间最短的活动可能会破坏掉原本可以参加的两个活动,但它一定不能破坏掉3个或以上原本可以参加的活动。这是因为中间那个活动一定会比原本选择那个活动要短(如图所示),这与贪心策略不符。
如果将我们的方案 A A A和最优解 O P T OPT OPT选择的活动各自以一列圆点表示出来,用直线相连表示活动间的不相容关系,那么根据上文的结论, A A A列的点最多有两个出度。一个可能的连接情况如下图所示。可见, O P T A ≤ 2 \frac{OPT}{A}\leq 2 AOPT≤2。