数学问题一般分为三类
对于活动选择问题,很多人应该对此感到很熟悉,它属于优化问题,问题描述:
假设有一组活动集合,S={ s1,s2,...,sn },这些活动同时只能使用同一个资源,而这个资源在某个时刻只能提供一个活动使用。每个活动 si 都存在有开始时间 ai 和 结束时 bi ,其中0 ≤ ai < fi < ∞ 。在活动问题中,我们希望选出一个组活动,使这些活动的数量最多,即能更好的利用当前资源。
如果用直接的想法,会是如下的解决方案:
其中第三条排序可以放到第一步去做,这样就不用每次都在选择集合中排序了。以上的解决方法遍历了所有可能的情况,至少存在一组集合不存在冲突,且兼容活动数量最大。不难发现最多共选择了n集合的所有非空子集合,为 2n−1 种情况,为非多项式时间的解决方案。
虽然遍历所有方案并不是一个可行的方法,但是至少确定先对问题进行排序可以方便运算与观察,并且基于比较排序本身所花费的时间为 O(nlogn) ,其实发现这些隐含的信息是很重要的,活动选择问题对活动的开始结束时间有着严格的限制,通过排序可以明显的发现这些限制,甚至很好的利用它们,即假定活动已按结束时间的单调递增顺序排序:
b1≤b2≤b3...≤bn−1≤bn
—————————————————————————————-
对于求解优化问题,首先可以试一试用动态规划的方法求解该问题。
需要验证:
定义:
Si j 表示在 si 结束之后开始,且在 sj 开始之前的结束活动集合。
Aij 表示 Si j 的所有相容子集的非空族, Mij 表示 Si j 的所有最大相容子集非空族, Nij 表示 Si j 的其中的一个最大相容子集,显然 Mij ⊆ Aij , Nij ∈ Mij 。
上面的一些定义是为了更好的理解问题的包含关系, Si j 可能包含多个相容子集,更可以包含多个最大相容子集,我们所关心的是其中的一个最大相容子集,并不要求获取所有的最大相容子集。
如图所示,其中
S17 ={ s3,s4,s5,s6 }, S18 ={ s3 },
M17 包含集合{ s3,s4 }、{ s3,s5 }、{ s3,s6 }
我们可能一开始可能不会很好地找到符合条件的规划,比如我们可能会想到下面的选择方法。
方法一:
通过:如下图所示( si ….. sn )表示待选剩余活动的集合。
很明显得到,图中标注的两个选择子问题是相同的,所以活动安排问题具有子问题重叠性。
按照上述那么活动安排问题是否具有最优子结构性质呢?
设 N 表示 Si n 的其中的一个最大相容子集,当考虑了活动 si 之后,那么得到子问题为寻找 Si+1,n 中的最大相容子集,设 M 为 Si+1,n 的最优解。
证明:若 M 不是 Si+1,n 的最优解,则存在 M0 是 Si+1,n 的最优解,即 |M0|>|M| ,假设选择了活动 si ,对于 M0 来说,虽然在 Si+1,n 是最优的,但是并不能保证跟已选择的活动相容,也就是说并不比 M0 优的选择 M 也能达到同样的选择结果。
反证并不成立,我们证明不了这种策略具有最优子结构,这种方法适用于动态规划。
首先说明上面定义的变量,下文中还会用到。
方法二:
如果只想到了方法一也没关系,其实只要对上述方法稍微改进一下就可以了,如果我们把上述的子问题改子问题为寻找 Si+1,n 中,且 其中每个活动都与 Si 兼容(添加了一种规则) 的最大相容子集成,那么我们的最有子结构性质就成立了(同样利用反证法),一旦最优子结构成立,我们就可以通过解决子问题来解决最终问题。
对于一般情况,从上文分析与最优子结构性质可以得出, N 的活动数为 M 加1,即 |N|=max|Mu|(i≤u≤n) ,也就是说只要逐次解决子问题就可以了。
时间上,我们不得不对所有活动两两比较,比较次数为 n(n−1)/2 。
空间上除输入需要2n个空间外,还有必要加上n个存储空间记录比较结果。