活动安排问题

问题表述:设有n个活动的集合E = {1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。

每个活i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si < fi 。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。
若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si >= fj或sj >= fi时,活动i与活动j相容。

由于输入的活动以其完成时间的非减序排列,所以算法greedySelector每次总是选择具有最早完成时间的相容活动加入集合A中。直观上,按这种方法选择相容活动为未安排活动留下尽可能多的时间。也就是说,该算法的贪心选择的意义是使剩余的可安排时间段极大化,以便安排尽可能多的相容活动。

算法greedySelector的效率极高。当输入的活动已按结束时间的非减序排列,算法只需O(n)的时间安排n个活动,使最多的活动能相容地使用公共资源。如果所给出的活动未按非减序排列,可以用O(nlogn)的时间重排。

例:设待安排的11个活动的开始时间和结束时间按结束时间的非减序排列如下:

算法greedySelector 的计算过程如下图所示。图中每行相应于算法的一次迭代。阴影长条表示的活动是已选入集合A的活动,而空白长条表示的活动是当前正在检查相容性的活动。


若被检查的活动i的开始时间Si小于最近选择的活动j的结束时间fi,则不选择活动i,否则选择活动i加入集合A中。

贪心算法并不总能求得问题的整体最优解。但对于活动安排问题,贪心算法greedySelector却总能求得的整体最优解,即它最终所确定的相容活动集合A的规模最大。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>using namespace std;struct ActivityTime
{public:ActivityTime(int nStart, int nEnd):m_nStart(nStart), m_nEnd(nEnd){ }ActivityTime(): m_nStart(0), m_nEnd(0){}friendbool operator < (const ActivityTime &lth, const ActivityTime &rth){return lth.m_nEnd < rth.m_nEnd;}public:int m_nStart;int m_nEnd;
};class ActivityArrange
{public:ActivityArrange(const vector<ActivityTime>&vTimeList){m_vTimeList = vTimeList;m_nCount = vTimeList.size();m_bvSelectFlag.resize(m_nCount, false);}void greedySelector(){__sortTime();                              // 以结束时间为依据排序 m_bvSelectFlag[0] = true;int j = 0;for (int i = 1; i < m_nCount; ++i){// 在结束时间递增的基础上,开始时间大于前者结束时间 ,即可视为最优排序 if (m_vTimeList[i].m_nStart > m_vTimeList[j].m_nEnd){        m_bvSelectFlag[i] = true;j = i;}}copy (m_bvSelectFlag.begin(), m_bvSelectFlag.end(), ostream_iterator<bool>(cout, " "));cout << endl;}private:void __sortTime(){sort(m_vTimeList.begin(), m_vTimeList.end());                   //通过重载 "<" 以结束时间为比较原则排序 for (vector<ActivityTime>::iterator ite = m_vTimeList.begin();ite != m_vTimeList.end();++ite){cout << ite->m_nStart << "," << ite->m_nEnd << endl;}}private:vector<ActivityTime> m_vTimeList;vector<bool> m_bvSelectFlag;int m_nCount;};int main()
{vector<ActivityTime> vActiTimeList ;vActiTimeList.push_back (ActivityTime(1, 4)) ;vActiTimeList.push_back (ActivityTime(3, 5)) ;vActiTimeList.push_back (ActivityTime(0, 6)) ;vActiTimeList.push_back (ActivityTime(5, 9)) ;vActiTimeList.push_back (ActivityTime(5, 7)) ;vActiTimeList.push_back (ActivityTime(3, 8)) ;vActiTimeList.push_back (ActivityTime(6, 10)) ;vActiTimeList.push_back (ActivityTime(8, 11)) ;vActiTimeList.push_back (ActivityTime(8, 12)) ;vActiTimeList.push_back (ActivityTime(2, 13)) ;vActiTimeList.push_back (ActivityTime(12, 14)) ;ActivityArrange aa (vActiTimeList) ;aa.greedySelector () ;return 0 ;
}

贪心算法《活动时间安排问题》相关推荐

  1. 《算法导论3rd第十六章》贪心算法

    前言 适用于最优化问题的算法往往包含一系列步骤,每个步骤都面临多种选择.使用动态规划解决最优化问题,相当于计算出每咱选择,浪费大量效率.对于"特定"下的最优化问题,可以使用更简单更 ...

  2. 《算法导论3rd第十五章》动态规划

    前言 和分治法一样, 动态规划 (dynamic programming)是通过组合子问题的解而解决整个问题的.分治法是将问题划分成一些独立的子问题,递归地求解各子问题,然后合并子问题的解而得到原问题 ...

  3. 《算法导论3rd第十九章》斐波那契堆

    前言 第六章堆排序使用了普通的二叉堆性质.其基本操作性能相当好,但union性能相当差. 对于一些图算法问题,EXTRACT-MIN 和DELETE操作次数远远小于DECREASE-KEY.因此有了斐 ...

  4. 《算法导论3rd第二十五章》所有结点对的最短路径问题

    前言 本章节,我们考虑"如何找到一个图中所有结点之间的最短路径"问题.我们通过运行|V|次上章节的单源最短路径算法解决所有结点对之间的最短路径问题,只需要每一次使用一个不同的结点作 ...

  5. 第十六章 贪心算法——0/1背包问题

    1.问题描述: 给定n种物品和一背包.物品i的重量是wi,其价值为vi,背包的容量为C.问:应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 形式化描述:给定c >0, wi > ...

  6. 【Java数据结构与算法】第十九章 贪心算法、Prim算法和Kruskal算法

    第十九章 贪心算法.Prim算法和Kruskal算法 文章目录 第十九章 贪心算法.Prim算法和Kruskal算法 一.贪心算法 1.介绍 2.支付问题 二.Prim算法 1.最小生成树 2.介绍 ...

  7. 算法设计与分析第3章 贪心算法

    第4章 贪心算法 贪心算法总是作出在当前看来最好的选择.也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择. 贪心算法的基本要素 1.贪心选择性质 所谓贪心选择性质是指所 ...

  8. 三十六、贪心算法--集合覆盖问题

    一.贪心算法介绍 1.贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解 2.贪心算法不是对所有问题都 ...

  9. 《算法导论》第十二章——二叉搜索树

      虽然写这个博客主要目的是为了给我自己做一个思路记忆录,但是如果你恰好点了进来,那么先对你说一声欢迎.我并不是什么大触,只是一个菜菜的学生,如果您发现了什么错误或者您对于某些地方有更好的意见,非常欢 ...

  10. 操作系统导论OSTEP 第十六章作业答案 分段

    答案Github库 https://github.com/jzplp/OSTEP-Answers 问题 1 答案 [testjz@localhost vm-segmentation]$ ./segme ...

最新文章

  1. 008 python接口 unittest
  2. 关于selenium+python的框架
  3. 【Linux】8.安装tensorrt和遇到的问题及解决方法
  4. 四、【SAP-PM模块】维护业务处理流程
  5. 代码生成器的存在价值 选择自 mechiland 的 Blog
  6. 更改python默认路径_Linux下多版本python共存时,默认执行路径修改方法
  7. div方框弯曲边样式_使用弯曲样式编辑文本
  8. 域名可以转让注册人吗_网店可以转让吗?
  9. 决定好好研究一些开源的系统
  10. LoadRunner11-遇到问题及解决办法
  11. OC算法练习-Hash算法
  12. 洛谷P2486 [SDOI2011]染色
  13. java 汉字排序_Java中文排序
  14. 基于matlab的QPSK系统仿真及应用
  15. nanomsg项目实战
  16. bilinear函数c语言怎么实现,bilinear和bicubic的算法封装
  17. gitlab将个人项目与他人共享设置
  18. mysql count判断_【MySQL】COUNT
  19. Java基础-程序基础
  20. wpf TextBox日志文本框

热门文章

  1. Kotlin苦海无涯(四) Object
  2. matlab版大学物理学,MATLAB可视化大学物理学(第2版)
  3. wps/excel 正则表达式 提取数字
  4. TensorFlow - 使用Eigen进行矩阵计算
  5. 简易火锅店点餐结算小程序
  6. matlab 曲线数据输出,Mathlab 如何输出曲线各数据点值?
  7. BZOJ1050 旅行comf
  8. Android平台第三方插件开发指导(dcloud)
  9. AWS架构师认证有什么用?考试难吗?
  10. linux 中 man 命令的介绍