你所不知道的贪心算法
假如公司组织爬山活动,需要带一些高糖分的水果。总价不超过100元。现在有4种水果可选:西瓜每500g5块5,含30g糖;桃子每500g7块5,含40g糖;荔枝每500g14块钱,含75g糖;苹果每500g11块钱,含50g糖;紫霞要如何在100块的预算之内,找到糖分最多的方案呢?
假设任何水果都要整斤购买,也就是说水果的重量只能是500的整倍数,这个问题可以使用穷举法分析,找出1329种组合,但是如果使用贪心算法可能就会减少很多计算量。
贪心算法,也叫做贪婪法,是一种非常常用的求最优解的方法。这种方法先把整个任务分割成一个一个的子问题,子问题之间存在相互依赖的关系,在一个子问题解决之后才能够解决下一个子问题,直到所有的子问题解决完。每一次解决子问题时都求出子问题的最优解,一般来说也就是求出子问题的最大值或者最小值。这也是贪心算法名字的缘由。
比如买水果的问题,可以先将问题分割成一个一个的小问题。先将每种水果的含糖量除以他的价格,得出单位价格的含糖量,对单位价格的含糖量进行排序,发现还是西瓜的单位价格含糖量最大,因此就尽可能的买西瓜。
这样可以买到18斤,也就是9000g的西瓜,花费99块钱。总糖分是540g。这时候通过贪心算法计算出来的结果只能买18斤西瓜,花费了99块钱,总糖分是540g。但是用穷举法得出的最好结果是545g糖分。贪心算法求出来的根本就不是最好的结果。但是仔细想一想,很多的时候你很在乎这5g的差距吗?事实上这就是贪心算法的特点了:虽然不一定能求出最好的结果,但一定是比较好的结果。
贪心算法是希望能够求出最优解,但是他求出的却不一定是最优解。这是因为,他虽然每一步都是最优的,但并不能保证整体上一定是最优。这就好比两个人都要从北京到广州,一个人坐飞机,从北京到天津,从天津到上海,上海到深圳,深圳到广州,可能要花十几个小时;
另一个人呢,从北京到广州,坐火车,可能只需要8个小时。难道飞机比火车还慢吗?
第一个人把整个路程分割成4段,每一段都坐最快的交通工具,但是并不一定整段路程就最快。换句话说,贪心算法,虽然每一步走的都很快,但是“目光短浅”,所以可能错过最优解。
这就好像你去爬山,周围都是树,挡住了你的视线,你找不到哪个方向是通往山顶的,那就观察一下脚下,看哪一个方向是向上的,最陡峭的,然后就朝着这个方向走。
这时候你走的每一步,在走的过程中都是最快的方向,但是,你很可能走到了一个小山坡,而不是真正的山顶。这就是贪心算法的局部最优解,你走到的终点可能在一个小范围之内是最高的,但是不是整座山的最高点。也就是说不是全局最优解。
其实生活中很多地方都有过这种的例子,比如我们的国家这么大,为了保证国家的安全,就要在全国布置防空雷达,每个雷达的监测范围都不一样,那要怎么安排最合适呢?按照贪心算法来说,可以每一次选择监测范围最大的雷达,布置到没有被监测的地区,这样就可以用比较少的雷达覆盖到全国,保证我们每天能够安全生活了。