基于贪心策略的活动选择问题
2017-03-16 01:09
369 查看
关于活动选择的问题:
1:问题描述
n个活动都有自己的开始和结束时间,但是每个活动都是占用同一个教室,问怎么安排活动能够使一天
内安排的活动总数最多。
2:算法解决思想
活动总共是从1到n总共n个,假设Sij表示的是活动ai结束之后,aj开始之前的全部活动,现在我们来求
Sij的一个最大兼容活动子集。假设Aij是满足这样条件的一个最大活动子集,并且它包含了活动ak。那么可
以将Aij分割为3部分,既Aij = Aik + ak + Akj。则Sij的最大兼容活动个数sum = |Aik| + 1 +|Akj|。
如果Aik不是活动Sik的一个最佳子集,那么必然存在一个Sik' > Sik,那么就会有sum' = |Aik’| + 1 + |Akj| > sum,
这根sum是Sij的最大兼容活动个数相违背,所以Aik必然是活动集Sik的一个最大兼容活动集,也就是说子问题Aik是子问题
的最优解。同理Akj也必然是子问题的最优解。这就满足了最优解的问题的子问题也是最优解的条件,预示着我们可以
使用动态规划来解决这个问题。
3:关键点的证明
虽然使用动态规划可以解决问题,但是动态规划的时间复杂度要高些,并且动态规划要解决的子问题比较多些。
贪心选择就是从直觉上选择当前应该是最佳的解决方案,那么两个子问题中因为有了贪心选择就只剩下一个待解决的
子问题了。在活动选择这里,我们做的选择就是结束最早的活动。那怎么证明最早结束的就一定存在在最优解中呢?
在这里有个定理:在非空子问题Sk中,如果am是Sk中结束最早的活动,那么am在Sk的某个最大兼容活动集中。
证明是这样的:设Ak是Sk的一个最大兼容活动集,且aj是Ak中最早结束的活动,若aj == am,则证明了定理,若
aj≠am,令Ak' = (Ak - aj)∪am,因为f(am) < f(aj),所以Ak’中的活动必然是不相交的,那么就可以得出Ak'也是Sk
的一个最大兼容活动子集。从而证明了定理。
4 代码实现
由于python代码接近于伪代码,所以这里采用python来实现算法
<1> 递归
<2> 非递归
5 参考文献
算法导论
1:问题描述
n个活动都有自己的开始和结束时间,但是每个活动都是占用同一个教室,问怎么安排活动能够使一天
内安排的活动总数最多。
2:算法解决思想
活动总共是从1到n总共n个,假设Sij表示的是活动ai结束之后,aj开始之前的全部活动,现在我们来求
Sij的一个最大兼容活动子集。假设Aij是满足这样条件的一个最大活动子集,并且它包含了活动ak。那么可
以将Aij分割为3部分,既Aij = Aik + ak + Akj。则Sij的最大兼容活动个数sum = |Aik| + 1 +|Akj|。
如果Aik不是活动Sik的一个最佳子集,那么必然存在一个Sik' > Sik,那么就会有sum' = |Aik’| + 1 + |Akj| > sum,
这根sum是Sij的最大兼容活动个数相违背,所以Aik必然是活动集Sik的一个最大兼容活动集,也就是说子问题Aik是子问题
的最优解。同理Akj也必然是子问题的最优解。这就满足了最优解的问题的子问题也是最优解的条件,预示着我们可以
使用动态规划来解决这个问题。
3:关键点的证明
虽然使用动态规划可以解决问题,但是动态规划的时间复杂度要高些,并且动态规划要解决的子问题比较多些。
贪心选择就是从直觉上选择当前应该是最佳的解决方案,那么两个子问题中因为有了贪心选择就只剩下一个待解决的
子问题了。在活动选择这里,我们做的选择就是结束最早的活动。那怎么证明最早结束的就一定存在在最优解中呢?
在这里有个定理:在非空子问题Sk中,如果am是Sk中结束最早的活动,那么am在Sk的某个最大兼容活动集中。
证明是这样的:设Ak是Sk的一个最大兼容活动集,且aj是Ak中最早结束的活动,若aj == am,则证明了定理,若
aj≠am,令Ak' = (Ak - aj)∪am,因为f(am) < f(aj),所以Ak’中的活动必然是不相交的,那么就可以得出Ak'也是Sk
的一个最大兼容活动子集。从而证明了定理。
4 代码实现
由于python代码接近于伪代码,所以这里采用python来实现算法
<1> 递归
# k is the activity which has finished and n has't finished def greedyActivity(s, f, k, n): m = k + 1 while (m <=n and s[m] < f[k]): m += 1 if(m <= n): x = [m]; x += greedyActivity(s, f, m, n) return x else: return [] #in order let the first activity in the result ,we must make up #an activity as the one activity finished before the first s = [-2,1,3,0,5,3,5,6,8,8,2,12] f = [-1,4,5,6,7,8,9,9,10,11,12,14,16] k = 0 n = 11 z = greedyActivity(s,f,k,n) print(z)
<2> 非递归
#make a for loop and every time findintg the earlist finished activity # then change the k value def greedyActivityAdvance(s,f,k,n): x = [s[1]] k = 1 for m in range(2,n+1) : if( s[m] >= f[k]): x.append(m) k = m return x s = [-2,1,3,0,5,3,5,6,8,8,2,12] f = [-1,4,5,6,7,8,9,9,10,11,12,14,16] k = 0 n = 11 zz = greedyActivityAdvance(s,f,k,n) print(zz)
5 参考文献
算法导论
相关文章推荐
- 贪心:活动选择问题
- 活动选择问题(贪心)
- 算法导论之贪心算法:活动选择问题
- 贪心算法之活动选择问题
- 贪心算法之活动选择问题
- (基于Java)算法之贪心算法——活动安排问题
- 活动选择问题的动归和贪心解法
- SDUTOJ 2073 —— 活动选择问题 贪心
- 贪心 活动选择问题 OJ
- 贪心算法--活动选择问题
- 贪心算法-活动选择问题
- 贪心算法的例子:活动选择问题
- 贪心算法--活动选择问题
- 数据结构 练习 19-活动选择问题的实现(动态规划 和 贪心)
- SDUT 贪心 活动选择问题
- 选择不相交区间(活动安排问题)(贪心)(HDU2037)
- 贪心算法之活动选择问题
- 贪心算法---活动选择问题
- 贪心法——活动选择问题和背包问题
- 贪心算法解决活动选择问题