贪心算法

Foreward:

Greed is human nature, curiosity is human motivation.
贪婪是人类的本性,求知是人类的动力。

今天要介绍的算法是贪心算法(Greedy),又名贪婪算法

整体会比较基础易懂

所以 What’s the greedy algorithm?

Definition:

A greedy algorithm is a simple, intuitive algorithm that is used in optimization problems. The algorithm makes the optimal choice at each step as it attempts to find the overall optimal way to solve the entire problem.
Wiki

简单来说,就是在每一步寻求当前最优解,不断追求局部最优,与之后会讲到的考虑全局最优的动态规划恰恰相反

使用贪心算法解决问题时,会将问题分为若干个子问题,利用贪心的原则从内向外依次求出当前子问题的最优解,也就是说会从小利益出发,从局部考虑问题,求得当前子问题的最优解,才能继续寻求下一个子问题的最优解,所以前一个子问题的最优解会是下一个子问题最优解的一部分,一直不断的一步步求子问题的最优解最终解决问题。

贪心算法最关键的部分在于贪心策略的选择,当贪心算法可以解决一个个子问题进而最终得到全局的最优解时,这就是一个不错的贪心算法。

需要注意的是,贪心算法的设计必须有“无后效性”的特点。

什么是无后效性呢?就是对于某个状态,也就是对于某个子问题的抉择,不会影响之前求得的局部最优解,否则就必须通过全局的考虑很分析来求得最终答案。

还有需要注意的是,贪心算法没有固定的解决方案,需要多加练习熟能生巧,当然用某个蒟蒻(就是彩笔)的话来讲,这是真正意义上开始学的第一个最基础的算法

贪心正确性的证明

方法一:数学归纳法

首先我们需要构造一个贪心的算法P(n)
我们使用第一或第二数学归纳法证明 P ( n ) P(n) P(n)

  • 第一数学归纳法:
    证明: P ( 1 ) P(1) P(1)为真;若 P ( n ) P(n) P(n)为真,则 P ( n + 1 ) P(n+1) P(n+1)为真。
  • 第二数学归纳法:
    证明: P ( 1 ) P(1) P(1)为真;若对所有 k < n k<n k<n,有 P ( k ) P(k) P(k)为真, 则 P ( n ) P(n) P(n)为真。

方法二:交换论证法

  1. 分析一般最优解与贪心法的解的区别,然后定义一种转换规则,使得从任意一个最优解出发,经过不断对解的某些成分的排列次序进行交换或者用其他元素替换,将这个解最终能够转变成贪心法的解。
  2. 证明在上述转换中解得优化函数值不会变坏。
  3. 证明上述转换在有限步结束。

最后总结一下贪心的基本做法

  • 建立数学模型来描述问题
  • 把求解的问题分成若干个子问题
  • 对每个子问题求解,得到子问题的局部最优解
  • 把子问题的解局部最优解合成原来问题的一个解

记得不是一眼题的话稍微证明一下正确性哦

好啦理论结束咯
我们来看几个非常简单的例子开始~

1. 教室调度问题

若有一个课表,作为一个好学的SCIE三好青年,你希望做出最佳的选课方案(将尽可能多的课程安排在课表之上)

课程 开始时间 结束时间
ADO社🔥1 9AM 10AM
Computer Science 9:30AM 10:30AM
ADO社🔥2 10AM 11AM
Sailing Lesson 10:30AM 11:30
ADO社🔥3 11AM 12 PM

很显然最佳选择是ADO社🔥+ADO社🔥+ADO社🔥

不草率的来分析一下,你不能让所有课都在课表上,因为有一些课程是由冲突的

你希望在这间教室上尽可能多的课,很显然这不是我的最优策略 (大雾)。如何选出尽可能多且时间不冲突的课程呢?

看似是一个有一些复杂的问题,但实际上简单到出乎意料

做法是这样的:

  • 选出结束最早的课,作为选中的第一节课
  • 接下来,在第一节课结束后开始的课中,选出结束最早的课,就是要选的第二节课。
  • 重复这个操作即可

我们来手玩一下这个过程

我们发现“ADO社🔥1”是这之中结束时间最早的,所以说第一个选择就是ADO社🔥1,然后剩余的课必须在10AM之后,于是你就愉快的不用去上Computer Science的课啦

课程 开始时间 结束时间 是否选择
ADO社🔥1 9AM 10AM
Computer Science 9:30AM 10:30AM
ADO社🔥2 10AM 11AM
Sailing Lesson 10:30AM 11:30
ADO社🔥3 11AM 12 PM

接下来,重复这个操作,根据贪心算法以及你好学生的优秀品质,你再次 很遗憾的失去了1h的划水时间(懂的都懂),前去ADO社🔥2好好学习[Fighting]

课程 开始时间 结束时间 是否选择
ADO社🔥1 9AM 10AM
Computer Science 9:30AM 10:30AM
ADO社🔥2 10AM 11AM
Sailing Lesson 10:30AM 11:30
ADO社🔥3 11AM 12 PM

最终你发现你的第三节课将继续留在ADO教室~

于是,你又将生命中的一个上午奉献 在了ADO。

好的,手玩完毕,相信很多人想问,这么草率的吗??!

在这里插入图片描述

其实这个题,确实只能说证明显然

实在要证明正确性的话:
从贪心算法得到的结果集进行倒推,去掉第一个活动,在剩下的活动中结束时间最早的活动B的结束时间一定不小于A,那么A活动一定合理的在最优解之中,同理可判断剩下的所有活动。

代码有需要的随时找我交流啦~ 之后一些比较重要的题会放上代码供参考的!

好的编了很久的故事讲完了,我们来看下一个题

2. 均分纸牌为题

这是一个非常经典的问题

Description:

N N N堆纸牌,编号分别为 1 , 2 , … , n 1,2,…,n 1,2,,n。每堆上有若干张, 但纸牌总数必为 n n n的倍数.可以在任一堆上取若干张纸牌,然后移动。移牌的规则为:在编号为 1 1 1上取的纸牌,只能移到编号为 2 2 2的堆上;在编号为 n n n的堆上取的纸牌,只能移到编号为 n − 1 n-1 n1的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。
例如: n = 4 , 4 n=4,4 n=44堆纸牌分别为: ① 9 ② 8 ③ 17 ④ 6 ① 9 ② 8 ③ 17 ④ 6 98176
移动三次可以达到目的:
从③取4张牌放到④ 再从③取3张放到②然后从②取1张放到①。
给定纸牌堆数 N N N以及每一堆纸牌的数量 a 1 . . . n a_1...n a1...n, 求即所有堆均达到相等时的最少移动次数
#输入1:
4
9 8 17 6
#输出1:
3

我们拿到这个题,注意到题中的一句话

纸牌总数必为N的倍数
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。

那么也就是说, 每一堆纸牌还需要的纸牌的数量或者需要移出纸牌堆的数量就是用每堆的纸牌数减去平均数
我们注意到

在编号为

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值