step by step.
目录
1. 活动安排问题
2. 贪心算法的基本要素
(1) 贪心选择
(2) 最优子结构性质
3. 贪心算法的证明
4. 装载问题
5. 多机调度问题
例题
动规与贪心的比较
贪心算法:总是作出在当前看来最好的选择。—— 局部最优选择
活动安排问题:设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si
。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。
贪心算法:活动i在相容活动集合A中,当且仅当A[i]的值为true。用变量j记录最近一次加入A的活动序号。
由于fj总是当前集合A中所有活动的最大结束时间,故活动i与当前集合A中所有活动相容的充分必要条件是:si≥fj,若活动i与活动j相容,则将i成为最新加入集合A中的活动,并取代活动j的位置。
template
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)
理解:
贪心选择:每个选择都是当前状态下局部最好选择。自顶向下进行。
(动规:每一步选择依赖于相关子问题的解,自底向上进行。)
最优子结构性质:一个问题的最优解包含其子问题的最优解。
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)
PS:0-1背包问题怎么装也装不过背包问题。 :)
先说明问题具有最优子结构性质;然后证明存在最优解包含贪心选择的第一步(即可以采用贪心选择来开始)。
最轻者先装。
多机调度问题 要求给出一种作业调度方案,使所给的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; iID = 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台机器M1,M2和M3加工处理。各作业所需的处理时间分别为{2,14,4,16,6,5,3}。按算法greedy产生的作业调度如下图所示,所需的加工时间为17。
标准分治 |
动态规划 |
贪心选择 |
|
适用类型 |
通用问题 |
优化问题 |
优化问题 |
子问题结构 |
每个子问题不同 |
很多子问题重复 |
只有一个子问题 |
最优子结构性质 |
满足 |
满足 |
满足 |
求解子问题数 |
全部子问题都要解决 |
全部子问题都要解决 |
只解决一个子问题 |
子问题在最优解里 |
全部 |
部分 |
部分 |
选择与求解次序 |
先选择后解决子问题 |
先解决子问题后选择 |
先选择后解决子问题 |
不写了我干没时间了拜拜!有空会补充的。
祝大家考试顺利: )