【算法设计与分析·复习】第四章-贪心算法||自食用

step by step.

目录

 1. 活动安排问题

2. 贪心算法的基本要素

(1) 贪心选择

(2) 最优子结构性质

3. 贪心算法的证明

4. 装载问题

5. 多机调度问题

例题 

动规与贪心的比较


贪心算法总是作出在当前看来最好的选择。—— 局部最优选择


 1. 活动安排问题

活动安排问题设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,si <fi 。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fjsj≥fi时,活动i与活动j相容。

贪心算法活动i在相容活动集合A中,当且仅当A[i]的值为true。用变量j记录最近一次加入A的活动序号。

·  将各活动的起始时间和结束时间存储于数组 s 和数组 f中。
·  按照 结束时间 的非递减顺序排列,即按照 f1≤f2≤…≤ fn 排列,可以用 O( nlogn )的时间进行排列。
·  一开始选择活动 1 j 初始化为 1 。然后依次检查活动 i是否与当前已选择的所有活动相容。
·  相容则将活动 i 加入到相容活动集合 A 中,否则不选择活动 i ,而继续检查下一活动与集合 A中活动的相容性。

     由于fj总是当前集合A中所有活动的最大结束时间,故活动i与当前集合A中所有活动相容的充分必要条件是:si≥fj,若活动i与活动j相容,则将i成为最新加入集合A中的活动,并取代活动j的位置。

template<class Type>
void GreedySelector(int n, Type s[], Type f[], bool A[])
{
       A[1]=true;
       int j=1;
       for (int i=2;i<=n;i++) {
          if (s[i]>=f[j]) { A[i]=true; j=i; }
          else A[i]=false;
          }
}

排序时间:O(nlogn)   贪心算法时间:O(n)

 理解:

2. 贪心算法的基本要素

(1) 贪心选择

贪心选择:每个选择都是当前状态下局部最好选择。自顶向下进行。

动规:每一步选择依赖于相关子问题的解,自底向上进行。)

(2) 最优子结构性质

最优子结构性质:一个问题的最优解包含其子问题的最优解。

0-1背包问题:(动规

满足最优子结构性质。但无法根据当前状态进行选择。


背包问题:(贪心

满足最优子结构性质,且可根据当前状态选择。

void Knapsack(int n,float M,float v[],float w[],float x[])
{
       Sort(n,v,w);
       int i;
       for (i=1;i<=n;i++) x[i]=0;
       float c=M;
       for (i=1;i<=n;i++) {
          if (w[i]>c) break;
          x[i]=1;
          c-=w[i];
          }
       if (i<=n) x[i]=c/w[i];
}

计算时间上界为O(nlogn) 

PS0-1背包问题怎么装也装不过背包问题。 :)

3. 贪心算法的证明

先说明问题具有最优子结构性质;然后证明存在最优解包含贪心选择的第一步(即可以采用贪心选择来开始)。

4. 装载问题

最轻者先装。

5. 多机调度问题

多机调度问题 要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。

贪心算法-多机调度问题C++_m0_46496993的博客-CSDN博客_多机调度问题贪心算法c++贪心算法-多机调度问题C++1.问题要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。约定,每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。作业不能拆分成更小的子作业。2.算法解析此算法的贪心策略主要在于Sort排序算法,按照作业时间从大到小进行排序。然后再考虑机器数量:(1)如果机器数量大于等于作业数,那么直接同时运行所有作业,其运行至少所需的时间就为所有作业中最大时间的那个作业的时间。(2)如果机器数小于作业数,则作业时间最少或者空闲的机器优先安https://blog.csdn.net/m0_46496993/article/details/106561923?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%A4%9A%E6%9C%BA%E8%B0%83%E5%BA%A6%E9%97%AE%E9%A2%98%20%E7%AE%97%E6%B3%95&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-9-106561923.first_rank_v2_pc_rank_v29&spm=1018.2226.3001.4187

int Dispatch(Job *a, Header *M, int n, int m){
	int min, max;
	JobNode *p, *q;     				//中间变量
	for(int i=0; i<n; i++){
		M[i].s = 0; M[i].next = NULL;   //将机器的总时间和作业指针初始化
	} 
	Sort(a, n);          //将a[]作业数组从小到大进行排序
	if(n <= m)
		return a[0].time;  //作业数小于机器数的情况,直接取排好序的作业数组第一个元素
	for(int j=0; j<n; j++){
		q = (pJobNode)malloc(sizeof(JobNode));   //给中间变量分配空间
		min = SelectMin(M, m);    //得出作业时间总和最小的机器的下标
		M[min].s += a[j].time;   
		q->ID = a[j].ID;		//将a数组中的元素变成作业节点数据
		q->time = a[j].time;
		q->next = NULL;			//尾指针置空
		if(!M[min].next)		//M未进行节点插入的情况,加入作业节点到头节点之后
			M[min].next = q;
		else{					//M已有作业节点的情况,加入作业节点到尾部
			p = M[min].next;
			while(p->next)
				p = p->next;
			p->next = q;
		}
	}
	Print(M, m);				//输出每台机器的运行作业的ID
	max = SelectMax(M, m);		//得出最大的s的机器的下标
	return M[max].s;			//返回至少需要的时间
}

① 当n<=m时,只要将机器i[0, ti]时间区间分配给作业i即可,算法只需要O(1)时间。

        ② 当n>m时,首先将n个作业依其所需的处理时间从大到小排序。然后依此顺序将作业分配给空闲的处理机。算法所需的计算时间为O(nlogn)

例题 

eg。

7个独立作业{1,2,3,4,5,6,7}3台机器M1M2M3加工处理。各作业所需的处理时间分别为{2,14,4,16,6,5,3}。按算法greedy产生的作业调度如下图所示,所需的加工时间为17

动规与贪心的比较

标准分治

动态规划

贪心选择

适用类型

通用问题

优化问题

优化问题

子问题结构

每个子问题不同

很多子问题重复

只有一个子问题

最优子结构性质

满足

满足

满足

求解子问题数

全部子问题都要解决

全部子问题都要解决

只解决一个子问题

子问题在最优解里

全部

部分

部分

选择与求解次序

先选择后解决子问题

先解决子问题后选择

先选择后解决子问题


不写了我干没时间了拜拜!有空会补充的。

祝大家考试顺利: ) 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值