问题:

有一个需要使用每个资源的n个活动组成的集合S= {a1,a2,···,an },资源每次只能由一个活动使用。每个活动a都有一个开始时间和结束时间,且 0<= s < f 。一旦被选择后,活动a就占据半开时间区间[s,f]。如果[s,f]和[s,f]互不重叠,则称两个活动是兼容的。该问题就是要找出一个由互相兼容的活动组成的最大子集。

定义子集合Sij = { ak  S : f i <= sk < f k <= s j}, 即每个活动都在ai结束之后开始,在aj开始之前结束,亦即Sij包含了所有和ai和aj兼容的活动。

假设S中的活动已按照结束时间递增的顺序排列,则Sij具有如下的性质:

1.当i <= j时,Sij 为空,

2.假设ak属于Sij,那么ak将把Sij分解成两个子问题,Sij包含的活动集合就等于Sik中的活动+ak+Skj中的活动。从这里就可以看出Sij的最优子结构性质:Sij的最优解包含了子问题Sik和Skj的最优解。假设Sij的最大兼容活动子集为Aij,那么有Aij = Aik U  ak U Akj。整个活动选择问题的最优解也是S0,n+1的解。

假设c[i,j]为Sij中最大兼容子集中的活动数。则有如下递归式:

C[i,j] = 0                       如果 Sij 为空

C[i,j] = max{c[i,k] + c[k,j] +1 }                   i < k < j & ak  Sij  如果Sij 不为空

根据这个递归式,可以得到一个动态规划解法。

// greedy_algorithm.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include<iostream>
#include<queue>
using namespace std;#define NofActivity 11    //有效的活动数
int c[NofActivity + 2][NofActivity + 2];   //c[i][j]存放第i个结束后第j个开始前兼容的活动个数
int reme[NofActivity + 2][NofActivity + 2];   //记录哪几个活动满足条件
//活动的结构/
struct Activity
{int num;   //活动的标号int start;   int finish;
};
//活动已经按结束时间的早晚排好序
//初始化活动结构数组,注意添加了了头和尾,活动有效数据只有11组,添加到13组的意思是找第0组结束之后,第12组开始之前可以兼容的那些活动组合
Activity Act[NofActivity+2] = { {0,0,0},{ 1,1,4 },{2,3,5 },{3, 0,6 },{4, 5,7 },{5, 3,9 },{6, 5,9 },{7, 6,10 },{8, 8,11 },{9, 8,12 },{10, 2,14 },{11, 12,16 }, {12,24,24}};///用队列来存储符合条件的活动,递归版本//
queue<Activity> select;
void Recursive_activity_selector(Activity* Act, int k, int n)
{//查找k结束之后第一个结束的活动int m = k + 1;while (m <= n&&Act[m].start < Act[k].finish)m++;//如果找到就把它入队,递归调用查找下一个if (m <= n){select.push(Act[m]);Recursive_activity_selector(Act, m, n);}
}///活动选择的迭代版本/
void Greedy_activity_selector(Activity* Act)
{//先把第一个入队int n = NofActivity;while (!select.empty())select.pop();select.push(Act[1]);//循环查找下一个满足条件的活动入队int k = 1;for (int i = 2; i <= n; i++){if (Act[i].start > Act[k].finish) {select.push(Act[i]);k = i;}}
}/活动选择的动态规划版本//
void activity_selector(Activity* Act)
{//初始化for (int i = 0; i <= NofActivity+1; i++){for (int j = 0; j <= NofActivity + 1; j++){c[i][j] = 0;reme[i][j] = 0;}}//从长度为2的开始查找for(int l=2;l<=NofActivity+2;l++)for (int i = 0; i <= NofActivity-l+3; i++)    //注意开始要从虚拟的活动0开始,到虚拟的活动NofActivity+1结束,这是由c[i][j]的定义所决定的{int j = i + l - 1;bool flag=false;                         //标志i,j之间是否含有兼容的活动for (int k = i + 1; k < j; k++){if (Act[k].start > Act[i].finish&&Act[k].finish < Act[j].start)  //c[i][j]定义的条件{if (c[i][j] < c[i][k] + c[k][j] + 1){c[i][j] = c[i][k] + c[k][j] + 1;//注意这里reme[i][j]的赋值,因为c[i][j] < c[i][k] + c[k][j] + 1,是小于号而不是小于等于,所以reme[i][j]会记录第一个满足条件的k,如reme[0][12]=1;reme[i][j] = k;}flag = true;                                    //有置1}}if (!flag)c[i][j] = 0;}//打印出c[i][j];for (int i = 0; i <= NofActivity + 1; i++) {for (int j = 0; j <= NofActivity + 1; j++)cout << c[i][j] << ' ';cout << endl;}
}//打印所选择的活动,act = reme[act][j]是由上诉对reme[i][j]的赋值规律所决定
void printSelect(int i, int j)
{int act = reme[i][j];while (act){cout << act << '\t';act = reme[act][j];}
}int main()
{//Recursive_activity_selector(Act, 0, NofActivity);/*Greedy_activity_selector(Act);while (!select.empty()){cout << select.front().num<< '\t';select.pop();}*/activity_selector(Act);printSelect(0, 12);while (1);return 0;
}

  

转载于:https://www.cnblogs.com/linear/p/6680132.html

活动选择的贪心算法与动态规划相关推荐

  1. 贪心算法和动态规划的区别

    一.动态规划  动态规划(简称DP)的思想是把一个大的问题进行拆分,细分成一个个小的子问题,且能够从这些小的子问题的解当中推导出原问题的解. 性质 1.最优子结构性:既所拆分的子问题的解是最优解. 2 ...

  2. 活动安排问题(贪心算法)

    问题描述: 有n个活动的活动集合E ,其中每一个活动都要求使用同一个资源,而在同一个时刻内资源只能被一个活动使用,每一个活动都有开始是时间和结束时间,要求从活动集合E中选出m个活动,使着m个活动都能顺 ...

  3. 算法设计之—直接 遍历/穷举法、贪心算法、动态规划、回溯法、EM方法

    算法是对完成特定问题的程序执行序列描述,表象为从问题初始状态到问题结束状态的所有路径之中寻找可行路径,若无先验经验,根据执行方式不同可以划分为无规则和有规则(启发式)方法. 无规则方法为穷举,改进方法 ...

  4. 活动安排问题--贪心算法

    活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子.该问题要求高效地安排一系列争用某一公共资源的活动.贪心算法提供了一个简单.漂亮的方法使得尽可能多的活动 ...

  5. 贪心算法与动态规划的区别与联系

    目录 1.定义 1.1贪心算法 1.1.1解题步骤 1.2动态规划 1.2.1解题步骤 2.联系 3.区别 1.定义 1.1贪心算法 贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择.也就是 ...

  6. 完全背包问题贪心算法c语言,数据结构与算法学习之路:背包问题的贪心算法和动态规划算法...

    一.背包问题描述: 有N种物品和一个重量为M的背包,第i种物品的重量是w[i],价值是p[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包重量,且价值总和最大. 二.解决方法: 1.贪心算 ...

  7. 剑指offer:剪绳子(找规律,贪心算法,动态规划)

    1. 题目描述 /* 题目描述给你一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x ...

  8. 分治,递归,贪心算法,动态规划的关系

    来自书籍<王道程序员面试宝典> 递归是解决问题的一种具体实现方法.而分治,动态规划,贪心算法是解决问题的一类思想. 分治一般通过递归实现.

  9. 活动选择问题 贪心

    活动选择问题 题目描述 sdut 大学生艺术中心每天都有n个活动申请举办,但是为了举办更多的活动,必须要放弃一些活动,求出每天最多能举办多少活动. 输入 输入包括多组输入,每组输入第一行为申请的活动数 ...

最新文章

  1. PCL:PCL与MFC 冲突总结
  2. Visual Studio 2017新版发布,极大提高开发效率丨附下载 1
  3. mysql in 按顺序排序_mysql in 排序 也可以按in里面的顺序来排序
  4. 关于map对key自定义排序
  5. Pandas-DataFrame基础知识点总结
  6. 【车联网】一文了解5G在车联网中的应用
  7. mysql常用功能点
  8. 坦克大战源代码java_Java版坦克大战游戏源码示例
  9. 阿里Maven仓库不限容量,免费用
  10. php mysql 嵌套查询_MySQL的嵌套查询_MySQL
  11. 遭遇 kapjazy.dll,yhpri.dll,WinSys64.Sys,nwiztlbu.exe,myplayer.com 等2
  12. 阿里淘宝Nginx升级版Tengine
  13. 师范类大学计算机排名,2018中国师范类大学排行榜,北京师范大学第一
  14. LED背光源的使用寿命多久?
  15. 点到点法式平面投影点的计算
  16. 46000\46001\46002\MNC\MCC\IMSI
  17. 如何彻底删除打印机驱动程序
  18. 6.Spring Cloud初相识-------Zool路由
  19. Python入门: 贪吃蛇详解
  20. Git 右键不显示Git功能图标

热门文章

  1. 【年度开源、工具合集】牛津计划,DMTK,Graph Engine…提高你的工作效率!
  2. 实时SLAM的未来及与深度学习的比较The Future of Real-Time SLAM and “Deep Learning vs SLAM”
  3. Python爬虫实战(1):爬取糗事百科段子
  4. Spark编程指南(Python版)
  5. sklearn svm
  6. 【转】使用python3的typing模块提高代码健壮性
  7. 进程间通信——POSIX 有名信号量与无名信号量
  8. ToString() 会发生装箱吗?
  9. Redis整合Spring结合使用缓存实例(转)
  10. R - 一只小蜜蜂...(第二季水)