疯子的算法总结(四)贪心算法

一、贪心算法

解决最优化问题的算法一般包含一系列的步骤,每一步都有若干的选择。对于很多最优化问题,只需要采用简单的贪心算法就可以解决,而不需要采用动态规划方法。贪心算法使所做的局部选择看起来都是当前最佳的,通过局部的最优化选择来产生全局最优解。本文将介绍贪心算法的理论基础和一些简单应用。在求最优解问题的过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。

设计贪心算法的步骤:

将最优化问题转化为这样一个问题,即先做出选择,再解决剩下的一个子问题。
证明原问题的最优解之一可以由贪心选择得到。
证明在做出贪心选择后,将剩余的子问题的最优解和我们所做的贪心选择组合起来,可以得到原问题的一个最优解。
一般,如果我们能证明一个问题具有以下两个关键的性质,那么就可以设计出它的一个贪心算法。

(1)贪心选择性质:一个全局最优解可以通过局部最优解(贪心)选择来达到。即,当考虑做选择时,只考虑对当前问题最佳的选择而不考虑子问题的结果。而在动态规划中,每一步都要做出选择,这些选择依赖于子问题的解。动态规划一般是自底向上,从小问题到大问题。贪心算法通常是自上而下,一个一个地做贪心选择,不断地将给定的问题实例规约为更小的子问题。
(2)含有最优子结构: 如果问题的一个最优解包含了其子问题的最优解,则称该问题具有最优子结构。**

利用贪心解决问题的关键需要考虑如何选取贪心标准。
贪心算法的理论基础
关于贪心算法有一种理论可用于确定在何时使用贪心算法能给出最优解,虽然这种理论并没有包含贪心算法所适用的所有情况,但确实描述了许多非常有意义的情况。

二、适用题型

1.活动选择问题。

这层楼沿着走廊南北向的两边各有200个房间。最近,公司要做一次装修,需要在各个办公室之间搬运办公桌。由于走廊狭窄,办公桌都很大,走廊里一次只能通过一张办公桌。必须制定计划提高搬运效率。经理制定如下计划:一张办公桌从一个房间移到另一个房间最多用十分钟。当从房间i移动一张办公桌到房间j,两个办公室之间的走廊都会被占用。所以,每10分钟内,只要不是同一段走廊,都可以在房间之间移动办公桌。

思路如果搬运桌子的路径有重叠,那么必定不能够同时进行,所以考虑每个房间经过的次数即为搬运的最短情况。

int i, j;
int move[200];
int N;        //搬运次数
//每次搬运的起点和终点
int from, to;
scanf("%d", &N);
memset(move, 0, sizeof(move));
for(i = 0; i < N; i++)
{
  scanf("%d%d", &from, &to);
  //将房间号映射为走廊号
  from = (from - 1)/2;
  to = (to - 1)/2;
  //确保from<to,C++使用:swap(from, to)
  if(from > to) {
    int temp = from;
    from = to;
    to = temp;
  }
  //占用走廊情况
  for(j = from; j <= to; j++)
    move[j]++;
}

2.可拆分背包问题

选出贪心准则,按照符合题意程度优先的顺序选择。
例如,去自助餐厅吃饭,要想吃回本就要捡着贵的吃,但是贵只是一方面,人会饱,所以用价格除以质量所获的价格商才是贪心准则,应按照价格商优先进行选取。

3.最优装载问题

有一批集装箱要装上一艘载重量为c的轮船,其中集装箱i的重量为wi。最优装载问题要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。

既然体积不受限制,只受质量限制,那可知从质量小的集装箱开始选取。

4.删数问题

string a;        //n位数a
int k;
cin>>a>>k;
//如果k≥n,数字被删完了
If (k >= a.size())  a.erase();
else while(k > 0)
{
  //寻找最近下降点
  int i;
  for (i=0; (i<a.size()-1) && (a[i] <= a[i+1]);  ++i);
  a.erase(i, 1);    //删除xi
  k- -;
}
//删除前导数字0
while(a.size() > 1 && a[0] == '0')
  a.erase(0, 1);
cout<<a<<endl;

5.多处最优服务次序问题


本题想让客户等待时间短,那如果让时间长的在前,就会有所用人等候最长时间人情况出现,肯定不为最优解。假设从最小的开始,人的基数乘以时间是一个小量,然后事间逐渐延长,人数减少。

6.多机调度问题

n个作业组成的作业集,可由m台相同机器加工处理。要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。作业不能拆分成更小的子作业;每个作业均可在任何一台机器上加工处理。这个问题是NP完全问题,还没有有效的解法(求最优解),但是可以用贪心选择策略设计出较好的近似算法(求次优解)。当n<=m时,只要将作业时间区间分配给作业即可;当n>m时,首先将n个作业从大到小排序,然后依此顺序将作业分配给空闲的处理机。也就是说从剩下的作业中,选择需要处理时间最长的,然后依次选择处理时间次长的,直到所有的作业全部处理完毕,或者机器不能再处理其他作业为止。如果我们每次是将需要处理时间最短的作业分配给空闲的机器,那么可能就会出现其它所有作业都处理完了只剩所需时间最长的作业在处理的情况,这样势必效率较低。

7.6.区间覆盖问题

POJ1328是一道经典的贪心算法例题。题目大意是假设海岸线是一条无限延伸的直线。陆地在海岸线的一侧,而海洋在另一侧。每一个小的岛屿是海洋上的一个点。雷达坐落于海岸线上,只能覆盖d距离,所以如果小岛能够被覆盖到的话,它们之间的距离最多为d。题目要求计算出能够覆盖给出的所有岛屿的最少雷达数目。对于每个小岛,我们可以计算出一个雷达所在位置的区间。

问题转化为如何用尽可能少的点覆盖这些区间。先将所有区间按照左端点大小排序,初始时需要一个点。如果两个区间相交而不重合,我们什么都不需要做;如果一个区间完全包含于另外一个区间,我们需要更新区间的右端点;如果两个区间不相交,我们需要增加点并更新右端点.

原文地址:https://www.cnblogs.com/lunatic-talent/p/11306473.html

时间: 2024-10-01 20:40:10

疯子的算法总结(四)贪心算法的相关文章

算法导论之贪心算法

参考:http://www.cnblogs.com/Creator/archive/2011/06/07/2074227.html 贪心算法在几个基本算法里面算是相对简单的算法了,思路也是非常简单的,每一步总是做出在当前看来最好的选择.也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择.基本思路就是从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解.当达到某算法中的某一步不能再继续前进时,算法停止. 贪心算法存在的问题是: 1. 不能保证求得的最

JAVA算法基础-贪心算法

前言 学无止境.算法博大精深啊,一个贪心算法里面就隐含了这么多不同的场景实现,每个场景下的算法就有多种不同的实现,个人写法不一也成就了各种不同的漂亮算法,看了这些实现,也让我开拓了思维,这个世界的方案永远没有最完美的只有最合适的- ! 1.贪心算法概念 贪心算法也叫贪婪算法,当然叫法随意.主要目的是在问题求解时,做出最正确的判断= =,这不是贪心是啥?在计算机工程领域当中,就是说不考虑整体最优算法而是从局部做到最优解.当然贪心是算法不能对所有的问题都能得到整体都最优解,但对多数个问题还是能得到近

(转)五大常用算法之三:贪心算法

http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741375.html 贪心算法 一.基本概念: 所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解. 贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择.必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态

五大常用算法之三:贪心算法

一.基本概念: 所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解. 贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择.必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关. 所以对所采用的贪心策略一定要仔细分析其是否满足无后效性. 二.贪心算法的基本思路: 1.建立数学模型来描述问题.2.把求解的问题分成若

【算法导论】贪心算法之活动选择问题

动态规划总是在追求全局最优的解,但是有时候,这样有点费时.贪心算法,在求解过程中,并不追求全局最优解,而是追求每一步的最优,所以贪心算法也不保证一定能够获得全局最优解,但是贪心算法在很多问题却额可以求得最优解. 一.问题概述 活动选择问题: 假定一个有n个活动(activity)的集合S={a1,a2,....,an},这些活动使用同一个资源(例如同一个阶梯教室),而这个资源在某个时刻只能供一个活动使用.每个活动ai都有一个开始时间si和一个结束时间fi,其中0<=si<fi<正无穷.如

【算法导论】贪心算法之赫夫曼编码

概述 讨论赫夫曼编码问题,赫夫曼编码的思想就是变长编码.变长编码就是让字符表中出现概率高的字符的编码长度尽可能小,而出现概率高的字符的编码长度相对较长.然后还要遵循前缀码的要求,就是任意一个编码都不是其他编码的前缀码,这样方便解码. 思路及实现 对于下表中的字符和相应的出现概率,有对应图中的编码树: 可以比较容易的看出来,每个叶节点就代表一个字符,从根节点到叶节点走过的路径拼接起来,就代表这个字符的编码,比如f是1100,e是1101,而f和e是深度最深的节点也是概率最小的两个节点.这也就是我们

经典算法学习之贪心算法

贪心算法也是用来求解最优化问题的,相比较动态规划很多问题使用贪心算法更为简单和高效,但是并不是所有的最优化问题都可以使用贪心算法来解决. 贪心算法就是在每个决策点都做出在当时看来最佳的选择. 贪心算法的设计步骤: 1.将最优化问题转换为:对其做出一次选择之后,只剩下一个问题需要求解的形式(动态规划会留下多个问题需要求解) 2.证明做出贪心选择之后,原问题总是存在最优解,即贪心算法总是安全的 3.证明做出贪心选择后,剩余的子问题满足性质:其最优解与贪心选择组合即可得到原问题的最优解,这样就得到了最

算法设计分析之贪心算法

贪心算法,是一种“只顾眼前”的价值观.远古的人会有这样的人生态度,我只关注每天能吃饱,就可以活下去.在几百万年前未尝不是一种好算法. 贪心算法的条件 贪心算法需要满足无后效性.什么是有后效性呢?我当前这一步会给整个问题的情况带来改变.比如有一个路径问题,规定了走过的路不能再走,那这就是一个有后效性的问题. 贪心算法也不适应那些活动收益不同的问题.比如背包问题:假设现在有几样价值不同,体积不同的东西需要装进容积为F的背包里,要求装入的总价值最大.用贪心算法来解,不能保证得到最优解. 贪心策略1:先

分治法、动态规划、回溯法、分支界限法、贪心算法

转:http://blog.csdn.net/lcj_cjfykx/article/details/41691787 分治算法一.基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并.这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)…… 任何一个可以用计算机求解的问题所需的计算时