核心算法6贪心算法

Posted joshuap

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了核心算法6贪心算法相关的知识,希望对你有一定的参考价值。

贪心算法就是遵循某种既定原则,不断地选取当前条件下最优的选择来构造每一个子步骤的解决方案,直到获得问题最终的求解。在对问题求解时,总是做出在当前看最好的选择。

也就是说,不从整体最优上考虑,所做的仅是在某种意义上的局部最优解。

利用贪心算法解题,需要解决两个问题

  1. 问题是否适合用贪心算法求解

    所求问题是否具有贪心选择性质
    贪心选择性质:是指应用同一种规则F,将原问题变为一个相似但规模更小的子问题,后面的每一步都是当前看来最佳的选择。这种选择依赖于已作出的选择,但不依赖与未作出的选择。从全局看,运用贪心策略解决的问题在程序的运行过程中无回溯过程。
    
  2. 问题是否具有局部最优解

    问题具有局部最优解,从而选择一个贪心标准,得到问题的最优解
    解题思路:
    1. 建立对问题精确描述的数学模型,包括定义最优解的模型
    2. 将问题分成一系列子问题,同时定义子问题的最优解结构
    3. 应用贪心算法可以确定每个子问题局部最优,并根据最优模型,用子问题的局部最优解堆叠出全局最优解
    
  • 硬币找零问题
  • 活动安排问题
  • 哈夫曼编码

硬币找零问题

问题描述

用最少硬币支付指定额度问题

假设,有6重不同面值的硬币,各硬币的面值分别为5分,1角,2角,5角,1元,2元。现要用这些面值的硬币来购物和找钱。购物时规定了可以使用的各种面值的硬币个数。假定商店里面各面值的硬币足够多,顾客也可以用多种方式支付。在一次购物中,希望使用最少硬币个数

举例,一名顾客需要付款0.55元,但顾客没有5角的硬币

  1. 第一种情况

    付款:0.2 + 0.2 + 0.1 + 0.05 = 0.55

    找零:0

  2. 第二种情况

    付款:1

    找零:0.2 + 0.2 + 0.05

  3. 第三种情况

    付款:1 + 0.05

    找零:0.5

那么,问题来了,对于给定的各种面值的硬币个数和付款金额,如何计算使用硬币个数最少的交易方案。

其核心思想为消费者硬币数量有限,商店的硬币数量无限,用公式描述:

  • MIN(消费者支付硬币个数 + 商店找零硬币个数)
  • 支付值 - 找零值 = 商品值

则问题转换为寻找上面两个问题的最优解,其贪心算法为:

? MAX(消费者拥有的硬币面值 - 商店拥有的硬币面值) 优先使用

假如,消费者拥有2元的硬币,商店拥有5分的硬币,因此MAX :2元 - 5分 = 195分

组合所有情况:

? 2元(不找零),2元 - 5分, 2元 - 1角,...... 5分(不找零)

接着验证该算法的贪心选择性和最优子结构性质,证明贪心算法可以获得最优解。

代码实现

import time

# 每种硬币的面值
coins = [0.05, 0.1, 0.2, 0.5, 1, 2]
# 每种硬币的数量
coin_num = []
s = 0

print("Separated by ‘,‘")
temp = input(‘Please enter the quantities of various change:‘)
coin_num0 = temp.split(‘,‘)

for i in range(len(coin_num0)):
    coin_num.append(int(coin_num0[i]))
    s += coins[i] * coin_num[i]

n_map = {
    ‘1‘: ‘One‘,
    ‘2‘: ‘Two‘,
    ‘3‘: ‘Three‘,
    ‘4‘: ‘Four‘,
    ‘5‘: ‘Five‘,
    ‘6‘: ‘Six‘,
    ‘7‘: ‘Seven‘,
    ‘8‘: ‘Eight‘,
    ‘9‘: ‘Nine‘,
    ‘10‘: ‘Ten‘
}

while True:
    time.sleep(0.2)
    sum = float(input(‘Please enter the amount of change you want:‘))
    # 当输入的总金额比收银员的总金额多, 无法进行找零
    if sum > s:
        print(‘The input amount is too large!‘)
        continue

    s = s - sum
    i = len(coins) - 1
    while i >= 0:
        if sum >= coins[i]:
            n = int(sum / coins[i])
            if n >= coin_num[i]:
                n = coin_num[i]
            # 关键, 令sum动态改变
            sum -= n * coins[i]
            print(‘%s %s-dollar COINS were used‘%(n_map.get(str(n)), n_map.get(str(coins[i]))))

        i -= 1
    break

以上是关于核心算法6贪心算法的主要内容,如果未能解决你的问题,请参考以下文章

763. 划分字母区间-贪心算法

贪心算法----区间覆盖问题(POJ2376)

从程序员进阶到架构师,6大核心技能要领详解

Contig|scaffold|N50|L50|NG50|贪心算法|de bruiji graph|

贪心算法应用-哈夫曼编码

程序员算法基础——贪心算法