python 实现贪心算法

贪心算法

一、 算法概述

1、 简介

贪心算法,又称贪婪算法,是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。[1]比如在旅行推销员问题中,如果旅行员每次都选择最近的城市,那这就是一种贪心算法。

贪心算法在有最优子结构的问题中尤为有效。最优子结构的意思是局部最优解能决定全局最优解。简单地说,问题能够分解成子问题来解决,子问题的最优解能递推到最终问题的最优解。

贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。

贪心法可以解决一些最优化问题,如:求中的最小生成树、求哈夫曼编码……对于其他问题,贪心法一般不能得到我们所要求的答案。一旦一个问题可以通过贪心法来解决,那么贪心法一般是解决这个问题的最好办法。由于贪心法的高效性以及其所求得的答案比较接近最优结果,贪心法也可以用作辅助算法或者直接解决一些要求结果不特别精确的问题。在不同情况,选择最优的解,可能会导致辛普森悖论,不一定出现最优的解。

2、 基本步骤

  1. 从某个初始解出发;
  2. 采用迭代的过程,当可以向目标前进一步时,就根据局部最优策略,得到一部分解,缩小问题规模;
  3. 将所有解综合起来。

二、 基本实现

1、 实例

这里,我们先使用一个找零钱的例子来模拟这个算法

找零钱问题假设你开了间小店,不能电子支付,钱柜里的货币只有 25 分、10 分、5 分和 1 分四种硬币,如果你是售货员且要找给客户 41 分钱的硬币,如何安排才能找给客人的钱既正确且硬币的个数又最少?这里需要明确的几个点:1.货币只有 25 分、10 分、5 分和 1 分四种硬币;2.找给客户 41 分钱的硬币;3.硬币最少化思考,能使用我们今天学到的贪婪算法吗?怎么做?

2、 分析步骤

  1. 初始解,我们可以从想找给顾客小于41中最大的硬币
  2. 使用迭代,不断的给客户找尽可能大的硬币,这样才能实现个数少的要求
  3. 将所有解综合起来

3、 代码实现

这里我们采用python来实现这个算法

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "test.py"
__time__ = "2022/7/24 12:16"

coin = [25, 10, 1, 5]  # 所有类型的硬币
coin.sort()  # 先对硬币的面值进行排序,后面采用出栈的形式来获取数据
# 定一个字典,存储使用了多少硬币
dic = {
   25: 0, 10: 0, 5: 0, 1: 0}  # 初始化字典
# 确定初始解
value = 41 - coin[-1]  # 初始条件为减去一个最大的值
dic[coin[-1]] += 1  # 这个也要自加1
while value > 0 and coin:  # 如果我们把钱找完,并且可以把
    if value - coin[-1] >= 0:
        value -= coin[-1]  # 对面值进行相减
        dic[coin[-1]] += 1  # 计数中自加1
    else:
        coin.pop()  # 如果不能再相减的话,就把这个硬币给弹出,不在考虑

print(dic)  # 最后我们输出结果

三、 数模实战

1、 题目展示

这里,我们使用的题目是2005年的数学建模大赛B,第二问:

表2中列出了网站手上100种DVD的现有张数和当前需要处理的1000位会员的在线订单(表2的数据格式示例如下表2,具体数据请从http://mcm.edu.cn/mcm05/problems2005c.asp下载),如何对这些DVD进行分配,才能使会员获得最大的满意度?请具体列出前30位会员(即C0001~C0030)分别获得哪些DVD。

数据请自己从网上下载哦!

表2:

DVD编号 D001 D002 D003 D004
DVD现有数量 10 40 15 20
C0001 6 0 0 0
C0002 0 0 0 0
C0003 0 0 0 3
C0004 0 0 0 0

2、 题目分析

2.1 公式

以一个月为一个周期,会员一个月可以租赁一次

忽略DVD在邮寄过程的时间

假设成员对每一个商品选择的序号为 a i j a_{ij} aij

则,我们取成员满意度为 d i j d_{ij} dij
d i j = { 1 a i j , a i j > 0 0 , a i j = 0 d_{ij} =\left\{\begin{matrix} \frac{1}{a_{ij}}, a_{ij} > 0 \\ 0, a_{ij}=0 \end{matrix}\right. dij={ aij1,aij>00,aij=0

同时,如果会员得到其选择的前三个商品,则其满意度应该为100%,故,设总满意度为:
D 0 = 1 + 1 2 + 1 3 D_{0} = 1 + \frac{1}{2} + \frac{1}{3} D0=1+21+31
那么,成员获取到DVD后的满意度可以表示为
D i = ∑ j = 0 3 a i j D 0 D_i = \frac{\sum_{j=0}^{3}{a_{ij}}}{D_0} Di=

  • 13
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SteveKenny

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值