贪心算法—活动选择问题
2015-06-01 20:05
295 查看
4.1 活动选择问题
1.问题的理解与描述
假定有n个需要使用同一个这样的资源的活动,每次只能有一个活动使用该资源。每一个活动有一个开始时间 si,一个完成时间 fi,其中0 ≤ si < fi < ∞。如果区间[si , fi)和[sj , fj)不相交,活动ai和aj是相容的(即如果si≥ fj 或 sj ≤ fi,ai和aj相容)。活动选择问题是选取一个由相容活动构成的最大集合。
输入:按完成时间排好序的活动开始时间数组s,完成时间数组 f。
输出:表示一个最大的相容活动组的向量{x1, x2, …, xn},其中
xi={01第i个活动在此最大相容活动组中否则,i1,2,...,n。x_i=
\begin{cases}
0& \text{第i个活动在此最大相容活动组中}\\
1& \text{否则}
\end{cases},i1,2,...,n。
2.最优子结构
定义集合
Sij=ak∈S:fi≤sk<fk≤sjSij = {a_k ∈ S : fi ≤ sk < fk≤ sj} ,为表示整个问题,添加两个假想的活动a0和an+1并约定f0 = 0及sn+1 = ∞。于是S = S0 n+1,而i和j的取值范围为0 ≤ i,j ≤ n + 1。显然只要i≥ j,就有Sij =∅。假定Sij的一个解包含活动ak,每一个都构成Sij中的活动的子集。设Aij是Sij的一个最优解,ak∈Aija_k∈A_{ij}。利用aka_k产生两个子问题: Sik和SkjS_{ik}和S_{kj},则Aij中Sik的解Aik和Skj的解Akj必对于: Sik和Skj也是最优的。
3.贪婪选择性
定理4-1
考虑任一非空子问题Sij,并设am为Sij中最早完成的一个活动:
fm=minfk:ak∈Sijf_m = min {f_k : a_k ∈ S_{ij}}。
则
(1)活动ama_m包含在SijS_{ij}的一个最大相容活动子集合中。
(2)子问题SimS_{im}是空的,所以选择ama_m将使得SmjS_{mj}成为仅有的非空子问题。
4.算法的伪代码描述
算法运行时间:Θ(n)
5 C++代码实现
运行结果:1 0 0 1 0 0 0 1 0 0 1
1.问题的理解与描述
假定有n个需要使用同一个这样的资源的活动,每次只能有一个活动使用该资源。每一个活动有一个开始时间 si,一个完成时间 fi,其中0 ≤ si < fi < ∞。如果区间[si , fi)和[sj , fj)不相交,活动ai和aj是相容的(即如果si≥ fj 或 sj ≤ fi,ai和aj相容)。活动选择问题是选取一个由相容活动构成的最大集合。
输入:按完成时间排好序的活动开始时间数组s,完成时间数组 f。
输出:表示一个最大的相容活动组的向量{x1, x2, …, xn},其中
xi={01第i个活动在此最大相容活动组中否则,i1,2,...,n。x_i=
\begin{cases}
0& \text{第i个活动在此最大相容活动组中}\\
1& \text{否则}
\end{cases},i1,2,...,n。
2.最优子结构
定义集合
Sij=ak∈S:fi≤sk<fk≤sjSij = {a_k ∈ S : fi ≤ sk < fk≤ sj} ,为表示整个问题,添加两个假想的活动a0和an+1并约定f0 = 0及sn+1 = ∞。于是S = S0 n+1,而i和j的取值范围为0 ≤ i,j ≤ n + 1。显然只要i≥ j,就有Sij =∅。假定Sij的一个解包含活动ak,每一个都构成Sij中的活动的子集。设Aij是Sij的一个最优解,ak∈Aija_k∈A_{ij}。利用aka_k产生两个子问题: Sik和SkjS_{ik}和S_{kj},则Aij中Sik的解Aik和Skj的解Akj必对于: Sik和Skj也是最优的。
3.贪婪选择性
定理4-1
考虑任一非空子问题Sij,并设am为Sij中最早完成的一个活动:
fm=minfk:ak∈Sijf_m = min {f_k : a_k ∈ S_{ij}}。
则
(1)活动ama_m包含在SijS_{ij}的一个最大相容活动子集合中。
(2)子问题SimS_{im}是空的,所以选择ama_m将使得SmjS_{mj}成为仅有的非空子问题。
4.算法的伪代码描述
RECURSIVE-ACTIVITY-SELECTOR (s, f, i, j) 1 m ← i + 1 2 while m < j 且 sm < fi 求Sij中的第一个活动 3 do xm←0 4 m ← m + 1 5 if m < j 6 then xm←1 7 RECURSIVE-ACTIVITY-SELECTOR (s, f, m, j)
算法运行时间:Θ(n)
5 C++代码实现
#ifndef _GREEDYACTIVITYSELECT_H #define _GREEDYACTIVITYSELECT_H int* RecusiveActivitySelector(int* s, int* f,int i,int j); #endif
#include "GreedyActivitySelect.h" int* RecusiveActivitySelector(int* s, int* f,int i,int j) { static int * x=new int[j]; int m=i+1; while(m<j&&s[m]<f[i])//求s[ij]中的第一个活动 { x[m]=0; m++; } if(m<j) { x[m]=1; RecusiveActivitySelector(s,f,m,j); } return x; }
#include "GreedyActivitySelect.h" #include <limits> #include <iostream> using namespace std; int main(int argc,char** argv) { int* x; int s[]={0,1,3,0,5,3,5,6,8,8,2,12,numeric_limits<int>::max()}, f[]={0,4,5,6,7,8,9,10,11,12,13,14,numeric_limits<int>::max()}; x=RecusiveActivitySelector(s,f,0,12); for(int i=1;i<12;i++) cout<<x[i]<<" "; cout<<endl; delete[]x; system("pause"); return (EXIT_SUCCESS); }
运行结果:1 0 0 1 0 0 0 1 0 0 1
相关文章推荐
- VB.NET vs. C#, round 2: Pounding on performance--VB.NET vs C#, 第二波:效率碰撞
- Android的四种启动模式-----深入理解
- Android 获取手机的一些基本信息
- Apache虚拟主机及别名配置
- hbase开发,hbase表操作及其java api实现
- 配置防火墙,开启80端口、3306端口
- 项目管理修炼之道(一 启动项目)
- 用苹果系统制作U盘引导安装苹果系统
- Android ThreadPoolExecutor 的参数详解
- 操作系统--进程的互斥与同步
- Android客户端与java服务器端的Socket连接
- 操作系统--进程的互斥与同步
- 正则表达式学习参考
- 初学Linux--shell
- Postfix邮件网关投递邮件报“fatal: open database /etc/postfix/transport.db: No su
- JSP连接mysql数据库分页查询
- java之Locale
- poj 3061 Subsequence
- Java工厂模式
- 拷贝控制