算法思想之贪心法

贪心法的基本思想

  贪心算法是利用问题的贪心性质,简化了分解原始问题的过程,每次只关注在当前状态下可以获得的局部最优解,通过凭借各阶段的局部最优解获得最终问题的解。

贪心法解决问题的条件

  1. 问题是否适用于贪心法求解,即索取求解问题是否具有贪心选择性质。
    贪心选择性质是指应用同一规则,将原问题变为一个相似的但规模更小的子问题,而后的每一步都是当前看似最佳的选择。
  2. 问题是否具有局部最优解,从而通过一个贪心标准,可以得到问题的最优解。

应用贪心法的基本思路

  • 建立对问题精确描述的数学模型,包括定义最优解的模型
  • 将问题纷纷昵称一系列子问题,同时定义子问题的最优解结构
  • 应用贪心算法原则可以却动每个子问题的局部最优解,并根据最优解模型,用字问题的局部最优解堆砌出全局的解

贪心法实例

1. 硬币找零问题

[问题描述] 假设市面上有6种不同面值的硬币,各硬币的面值分别为5分、1角、2角、5角、1元、2元,要找零10.5元,求出最少硬币的数量。

'''
贪心法--硬币找零问题

假设市面上有6种不同面值的硬币,各硬币的面值分别
为5分、1角、2角、5角、1元、2元,要找零10.5元,求出最少硬币的数量

本题选择的贪心策略为:总是选择当前面值最大的硬币
'''

import collections
def getChange(coins, amount):
    # 存放结果
    res = collections.OrderedDict()
    # 将硬币面值按从大到小排列
    coins.sort()
    coins.reverse()

    for each in coins:
        if amount >= each:
            n = int(amount // each)
            res[each] = n
            amount -= n * each
    return res


    # print(coins)


coins = [0.05, 0.1, 0.2, 0.5, 1, 2]
amount = 10.5
res = getChange(coins, amount)
print('共需',end='')
for key, value in res.items():
    print(f'{value}枚{key}元硬币',end=' ')
    

[结果] 共需5枚2元硬币 1枚0.5元硬币

2. 活动安排问题

[问题描述] 学校有开学典礼、课外讲座、话剧演出、音乐会、芭蕾舞演出和教职工会议等一系列活动
需要在礼堂矩形,具体活动信息如下,怎么安排才能是尽可能多的活动得以开展?

活动 开学典礼 课外讲座 话剧演出 音乐会 芭蕾舞演出 教职工会议
开始时间(s) 1 3 0 5 3 7
结束时间(f) 3 4 4 7 6 8
'''
贪心法-活动安排问题
学校有开学典礼、课外讲座、话剧演出、音乐会、芭蕾舞演出和教职工会议等一系列活动
需要在礼堂矩形,具体活动信息如下,怎么安排才能是尽可能多的活动得以开展?
*****************************************************************
  活动    *开学典礼*课外讲座*话剧演出*音乐会*芭蕾舞演出*教职工会议
*****************************************************************
开始时间 s*   1   *   3   *    0   *  5  *    3    *    7
*****************************************************************
结束时间 f*   3   *   4   *    4   *  7  *    6    *    8

本体采用的贪心策略为:总是选择最早结束的活动
'''

# 对结束时间进行排序,同时得到对应的开始时间的list
def insert_sort(s ,f):
    # 插入排序
    for i in range(1, len(s)): # 未排序的序列
        for j in range(i): # 已排序的序列
            if f[j] > f[i]:
                temp_s = s.pop(i)
                temp_f = f.pop(i)
                s.insert(j, temp_s)
                f.insert(j, temp_f)
                break
    return s,f

def greedy_activity(s, f):
    res = []
    a = [True for x in range(len(s))]
    j = 0
    for i in range(1, len(s)):
        if s[i] >= f[j]:
            a[i] = True
            j = i
        else: a[i] = False
    for k in range(len(a)):
        if a[k]:
            res.append((s[k],f[k]))
    return res


s = [1,3,0,5,3,7]
f = [3,4,4,7,6,8]

s, f = insert_sort(s, f)
res = greedy_activity(s,f)

print(res)

[结果] (1, 3), (3, 4), (5, 7), (7, 8)

你可能感兴趣的:(基本算法,贪心算法)