博客
关于我
09_Python算法+数据结构笔记-分数背包-数字拼接-活动选择-动态规划-钢条切割
阅读量:797 次
发布时间:2019-03-25

本文共 2161 字,大约阅读时间需要 7 分钟。

贪心算法及其应用

在算法设计中,贪心算法是一种有效且高效的策略,其基本思想是通过局部最佳选择来达到全局最优解。贪心算法广泛应用于多个领域,包括背包问题、活动选择问题、数字拼接以及钢条切割问题等。本文将从贪心算法的基本原理出发,分析其在多个典型问题中的应用。

背包问题

贪心算法适用情况

背包问题主要有两种形式:0-1背包和分数背包。两者的区别在于是否允许对同一物品进行多次选择或部分选择。

  • 0-1背包:每个物品只能选择一次,无法拆分。
  • 分数背包:允许对物品进行部分选择或多次选择。

贪心算法在这两种背包问题中并不适用。分数背包可以通过特定的贪心策略(按单位重量价值排序)得到最优解,但0-1背包需要使用动态规划等更复杂的算法。

贪心算法实例

以一个例子为例,假设我们有以下商品:

  • 商品1:价值60元,重量10千克
  • 商品2:价值100元,重量20千克
  • 商品3:价值120元,重量30千克

背包容量为50千克。分数背包算法的实现步骤如下:

goods = [(60, 10), (100, 20), (120, 30)]goods.sort(key=lambda x: x[0] / x[1], reverse=True)m = [0 for _ in range(len(goods))]total_v = 0w = 50for i, (price, weight) in enumerate(goods):    if w >= weight:        m[i] = 1        total_v += price        w -= weight    else:        m[i] = w / weight        total_v += m[i] * price        w = 0        breakprint(fractional_backpack(goods, 50))

结果为 (240.0, [1, 1, 0.6666666666666666]),即选取商品1和2,每个物品取完整,再加上商品3的部分。

数字拼接问题

贪心策略的局限性

在数字拼接问题中,贪心策略(按首位排序)虽然能快速得到结果,但并非总能得到最大值。例如,128和1286的拼接顺序决定了最终结果的不同。

  • 128 + 1286 = 1281286
  • 1286 + 128 = 1286128

显然,后一种拼接方式更优。

贪心算法优化

为避免贪心策略的局限性,可以采用以下优化策略:

  • 比较两数拼接:定义一个比较函数,判断 a + b 是否大于 b + a
  • 排序优化:对数字列表进行自定义排序,尽量避免短字符串与长字符串的部分重叠。
  • from functools import cmp_to_keyli = [32, 94, 128, 1286, 6, 71]li.sort(key=cmp_to_key(lambda x, y: (x + y) > (y + x) ? -1 : 1 : 0))print(''.join(str(x) for x in li))

    最终结果为 94716321286128,这是最优拼接结果。

    活动选择问题

    贪心算法的适用性

    活动选择问题的目标是选择最大数量的不重叠的活动。贪心算法通过选择最早结束的活动作为优先选择,能够快速找到最优解。

    贪心算法实现

    活动按照结束时间排序后,逐步选择不冲突的活动。

    activities = [(1, 4), (3, 5), (0, 6), (5, 7), (3, 9), (5, 9), (6, 10), (8, 11), (8, 12), (2, 14), (12, 16)]activities.sort(key=lambda x: x[1])res = [activities[0]]for activity in activities[1:]:    if activity[0] >= res[-1][1]:        res.append(activity)print(res)

    最终结果包含4场活动:[(1, 4), (5, 7), (8, 11), (12, 16)]。

    钢条切割问题

    贪心策略的挑战

    钢条切割问题需要考虑所有可能的切割方案,选择收益最大的方案。直接递归方法在算法复杂度上表现极差。

    动态规划优化

    通过动态规划,避免重复计算,实现高效的递推式:

    def cut_rod(p, n):    if n == 0:        return 0    r = [0] * (n + 1)    for i in range(1, n + 1):        max_val = p[i]        for j in range(i + 1, n + 1):            max_val = max(max_val, p[j] + cut_rod(p, j - 1 - i))        r[i] = max_val    return r[n]

    动态规划的核心在于存储已计算的子问题结果,避免重复计算。

    通过对比可发现,动态规划算法大大提高了效率,适合处理较大规模的钢条切割问题。

    转载地址:http://xctuk.baihongyu.com/

    你可能感兴趣的文章
    Nginx反向代理与正向代理配置
    查看>>
    Nginx反向代理及负载均衡实现过程部署
    查看>>
    Nginx反向代理和负载均衡部署指南
    查看>>
    Nginx反向代理是什么意思?如何配置Nginx反向代理?
    查看>>
    nginx反向代理解决跨域问题,使本地调试更方便
    查看>>
    nginx反向代理转发、正则、重写、负摘均衡配置案例
    查看>>
    Nginx反向代理配置
    查看>>
    Nginx启动SSL功能,并进行功能优化,你看这个就足够了
    查看>>
    nginx启动脚本
    查看>>
    Nginx和Tomcat的区别
    查看>>
    Nginx在Windows上和Linux上(Docker启动)分别配置基本身份认证示例
    查看>>
    Nginx在Windows下载安装启动与配置前后端请求代理
    查看>>
    Nginx在开发中常用的基础命令
    查看>>
    Nginx基础知识点与使用场景梳理
    查看>>
    Nginx多域名,多证书,多服务配置,实用版
    查看>>
    nginx如何实现图片防盗链
    查看>>
    Nginx学习总结(10)——Nginx前后端分离将多个请求转发到多个Tomcat,负载均衡反向代理
    查看>>
    Nginx学习总结(11)——提高Nginx服务器的安全性,稳定性和性能的12种技巧
    查看>>
    Nginx学习总结(12)——Nginx各项配置总结
    查看>>
    Nginx学习总结(13)——Nginx 重要知识点回顾
    查看>>