贪心算法与动态规划

1. 什么是贪心算法?

贪心算法是一种在每一步选择中都采取在当前状态下最好最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。

核心思想:“每步都贪心地选择眼前最好的,不去考虑整个未来的长远情况”。

它就像我们生活中“只顾眼前利益”的决策方式。例如,在找零钱时,为了凑出某个金额,我们总是先给出最大面额的钞票,然后再给更小的,这就是一种贪心思想。

2. 贪心算法的基本要素

一个问题是适用于贪心算法,通常需要具备两个重要的性质:

  1. 贪心选择性质

    • 定义:一个问题的全局最优解可以通过一系列局部最优的选择(即贪心选择)来达到。
    • 解释:这是贪心算法可行的前提。它要求我们在做贪心选择时,不会影响子问题的解。也就是说,我们做完一次选择后,只需要解决一个更小的子问题,而不需要回头重新考虑之前的选择。
  2. 最优子结构

    • 定义:一个问题的最优解包含其子问题的最优解。
    • 解释:这是动态规划和贪心算法都具备的性质。如果整个问题的最优解可以由各个子问题的最优解推导出来,那么我们就说这个问题具有最优子结构。

简单来说:贪心算法在每一步做出一个不可撤回的决策,并且希望每一步的局部最优能最终堆砌出全局最优。

3. 贪心算法的基本步骤

  1. 建立数学模型:将问题抽象为一个数学决策模型。
  2. 分解问题:将待求解的问题分解成若干个子问题。
  3. 制定贪心策略:根据题意,选择一个贪心准则,决定如何做出当前的最优选择。这是贪心算法的核心和难点。
  4. 求解子问题:根据贪心策略,一步步得到子问题的局部最优解。
  5. 组合成最终解:将所有的局部最优解组合成原问题的一个解。

4. 经典示例

示例1:找零钱问题

问题:假设硬币体系是 1元、5角、1角、5分、1分。现在要找给顾客 1元8角6分,如何找零才能使找零的硬币个数最少?

贪心策略每一步都使用当前可用的最大面额的硬币

步骤

  1. 1元8角6分 = 186分
  2. 先找 1元(100分),剩余 86分。
  3. 找不了1元了,找 5角(50分),剩余 36分。
  4. 找不了5角了,找 1角(10分),可以找3个,剩余 6分。
  5. 找 5分(5分),剩余 1分。
  6. 找 1分(1分),完成。

找零方案为:1个1元,1个5角,3个1角,1个5分,1个1分。总共 7 枚硬币

为什么这是有效的? 在这个特定的硬币体系( canonical coin systems )中,贪心算法总能得到最优解。但注意,如果硬币体系很奇怪(例如有 1分, 3分, 4分),要凑出 6分:

  • 贪心法:先拿4分,剩余2分,再拿两个1分,共3枚硬币(4,1,1)。
  • 最优解:其实是两个3分,共2枚硬币(3,3)。
    所以,贪心算法并不总是能得到最优解!
示例2:活动选择问题

问题:有一系列活动,每个活动有开始时间和结束时间。同一时间只能进行一个活动。如何选择才能使能进行的活动数量最多?

贪心策略每次都选择结束时间最早的活动,这样就能为后续活动留下更多的时间。

步骤

  1. 将所有活动按结束时间从早到晚排序。
  2. 选择第一个结束的活动。
  3. 接下来,选择开始时间晚于或等于上一个已选活动结束时间的活动中,结束时间最早的那个。
  4. 重复步骤3,直到没有活动可选。

这个策略被证明总能得到最优解。

5. 贪心算法 vs 动态规划

这是一个常见的困惑点,因为它们都用于求解优化问题且都具有最优子结构性质。

特性贪心算法动态规划
决策方式每步做一个不可撤回的决策,不考虑未来每步决策依赖于子问题的解,需要保存所有子问题的解并根据这些解做出决策。
子问题做出一次贪心选择后,只产生一个子问题通常会产生多个重叠子问题
效率高效,通常时间复杂度更低。相对较低,因为需要解决所有子问题。
适用范围要求问题具有贪心选择性质适用范围更广,只要具有最优子结构(即使没有贪心选择性质)。
结果不一定得到全局最优解总是得到全局最优解

关键区别:动态规划在做出决策时,需要考虑所有可能的选择(通常通过比较得出);而贪心算法则直接做出一个“看似最好”的选择,并且不再回头。

6. 贪心算法的优缺点

优点

  • 高效:算法通常简单、直接,时间复杂度低。
  • 易于实现:逻辑清晰,代码通常不长。

缺点

  • 局部最优不等于全局最优:这是最大的陷阱。很多问题无法用贪心算法得到真正的最优解。
  • 证明困难:如何证明一个贪心策略一定能得到全局最优解,通常是比较困难的。

7. 如何判断能否使用贪心算法?

这是一个没有万能公式的问题,但可以遵循以下思路:

  1. 先尝试:先想一个贪心策略,然后用一些简单的测试用例(尤其是边界 case)去验证它是否能得到最优解。
  2. 举反例:尝试思考是否存在一种情况,让你的贪心策略会做出错误的选择。如果能轻易找到反例,则说明贪心算法不适用。
  3. 数学证明:尝试从数学上证明该问题具有贪心选择性质最优子结构。这需要较强的数学功底,也是算法竞赛和研究的重点。

总结

贪心算法是一种强大而直观的“短视”算法。它通过一系列局部最优决策来构建解,期望最终得到全局最优解。

  • 核心:制定正确的贪心策略
  • 关键:问题必须具有贪心选择性质最优子结构
  • 陷阱:局部最优不一定是全局最优。
  • 对比:与动态规划相比,它更高效但不总是最优;动态规划更通用但更耗时。

掌握贪心算法需要大量的练习,去熟悉各种经典问题(如霍夫曼编码、最小生成树-Prim和Kruskal算法、单源最短路径-Dijkstra算法等)的贪心策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/98034.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/98034.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学会“读网页”:生成式 AI 在足球赛事信息整理中的实战

逐步教程(Step-by-Step) — 适合初学者与教学类文章 背景(为什么要这样做) 对于足球迷、资讯编辑与数据分析师来说,最快、最准确把握一场比赛的核心信息至关重要:比分、关键事件(进球、点球、红…

BM3D 图像降噪快速算法的 MATLAB 实现

BM3D 图像降噪快速算法的 MATLAB 实现1. 快速 BM3D 算法流程(概述)步骤操作加速技巧① 分组块匹配 堆叠FFT 互相关② 协同滤波3D 变换 硬阈值FFT 沿第三维③ 聚合加权平均稀疏矩阵累加 2. 核心函数(单文件版) 保存为 bm3d_fast.…

Go的schedt调度(runtime/proc.go)

1. 创建go的入口函数// Create a new g running fn. // Put it on the queue of gs waiting to run. // The compiler turns a go statement into a call to this. func newproc(fn *funcval) {gp : getg()pc : sys.GetCallerPC()systemstack(func() {newg : newproc1(fn, gp, …

Ubuntu 服务器配置转发网络访问

配置文档:Ubuntu 服务器转发网络访问 一、网络拓扑以以下网络拓扑为示例Ubuntu 服务器(两个网卡) eth1 10.66.71.222 (接入内网)eno1 192.168.2.100 (直连相机) 相机ip 192.168.2.1 Windows 客…

为什么企业需要高防IP

1. 抵御日益猖獗的DDoS攻击 现代DDoS攻击规模已突破Tbps级别 传统防火墙无法应对大规模流量攻击 高防IP采用分布式清洗中心,可轻松抵御300Gbps以上的攻击流量 2. 保障业务连续性 网络中断1小时可能造成数百万损失 高防IP确保服务99.99%可用性 智能切换机制实…

CSS基础 - 选择器备忘录 --笔记5

目录基础选择器组合器伪类选择器属性选择器选择器可以选中页面上的特定元素并为其指定样式。 CSS有多种选择器。 基础选择器 标签选择器 – tagname:匹配目标元素的标签名。优先级是0,0,1。如:p、h1、div类选择器 – .class:匹配class属性中…

自动驾驶中的传感器技术46——Radar(7)

卫星雷达(又称为分布式雷达)主要讲当前雷达的雷达信号处理计算以及雷达目标相关的一些感知算法都迁移到中央域控进行,雷达端基本只负责数据采集,这样做的影响如下: 雷达端成本与功耗降低; 雷达端采样得到的…

【论文阅读】Diff-Privacy: Diffusion-based Face Privacy Protection

基于扩散模型的人脸隐私保护方法——DiffPrivacy,解决了两类人脸隐私任务:匿名化(anonymization)和视觉身份信息隐藏(visual identity information hiding)。1. 研究背景随着人工智能和大数据技术的普及&am…

React 原理篇 - 深入理解虚拟 DOM

一、什么是虚拟 DOM? 在前端开发中,“虚拟 DOM” 是一个高频出现的术语,尤其在 React 生态中被广泛讨论。但很多开发者对它的理解往往停留在 “JS 对象” 这个表层认知上。 实际上,虚拟 DOM 是一种编程概念—— 在这个概念里&…

对汇编的初理解

此处是一个简单的函数,里面将调用了一个函数add()函数这里是函数的原型这里是调用lcd函数产生的汇编语言,翻译过来就是r11,r0cnt(r4cnt,前文有提及),然后调用add函数,此处BL是指会回到指令的下一…

《Python 自动化实战:从零构建一个文件同步工具》

《Python 自动化实战:从零构建一个文件同步工具》 一、开篇引入:为什么我们需要文件同步? 你是否有过这样的困扰: 公司电脑和家里电脑上都有工作项目,每次更新都要手动复制? U 盘频繁传输文件,不仅麻烦还容易出错? 项目文件夹动辄几 G,每次同步都耗时长、效率低? 在…

工业相机与镜头的靶面尺寸详解:选型避坑指南

在机器视觉系统中,相机与镜头的靶面尺寸匹配是一个非常关键却又经常被忽略的细节。选错了,不但影响图像质量,还可能导致画面“黑角”、视野不符、镜头浪费等问题。 今天我们就用通俗易懂的方式,聊一聊相机与镜头靶面尺寸的那些事儿…

使用 Go 和 go-commons 实现内存指标采集并对接 Prometheus

文章目录一、准备工作二、编写内存采集代码三、运行 Exporter四、接入 Prometheus五、可扩展思路总结在运维和监控领域,资源指标采集 是必不可少的一环。CPU、内存、磁盘、网络这些系统资源,需要实时采集并上报到监控系统中。 本文以 内存指标采集 为例&…

webrtc弱网-IntervalBudget类源码分析与算法原理

一、核心功能 IntervalBudget 类用于基于时间窗口的带宽预算管理。它根据设定的目标比特率(kbps)和一个固定时间窗口(500ms),计算在该时间窗口内可用的字节数(即“预算”),并支持预…

深度学习基本模块:RNN 循环神经网络

循环神经网络(RNN)是一种专门用于处理序列数据的神经网络架构。与处理空间数据的卷积神经网络(Conv2D)不同,RNN通过引入循环连接使网络具有"记忆"能力,能够利用之前的信息来影响当前的输出&#…

React18学习笔记(二) React的状态管理工具--Redux,案例--移动端外卖平台

文章目录一.Redux的基础用法1.示例:普通网页中的Redux计步器2.Redux管理数据的流程3.配套工具和环境准备3.1.配套工具3.2.环境准备4.示例:React项目中的Redux计步器思路步骤step1:创建子模块step2:导入子模块step3:注入store实例step4:React组件内使用store中的数据step5:在组件…

34.Socket编程(UDP)(上)

点分十进制字符串IP 转 32位网络序列IP 分析:1)IP转成4字节 2)4字节转成网络序列 思路: "192.168.1.1" 进行字符串划分,以 "." 为分割符,分割出"192",&qu…

Redis的持久化工具包—RDB AOF

文章目录 前言 一、RDB 持久化(快照持久化) 1. 定义 2. RDB 触发机制 (1)手动触发 (2)自动触发 3. RDB 持久化流程 4. RDB 核心配置 5. RDB 优缺点 二、AOF 持久化(日志持久化) 1. 定…

【Web安全】XXL-JOB框架SRC高频漏洞分析总结

文章目录前言一、核心漏洞分类与技术细节二、漏洞关联利用与攻击路径三、版本演进与修复策略四、安全运维建议五、典型漏洞复现环境搭建六、总结前言 XXL-JOB是国内主流的开源分布式任务调度框架,由徐雪里开发维护,以轻量易用、高可用、适配分布式场景等…

Capacitor 打包后接口访问不到的排查经历

我最近在用 Quasar Capacitor 6 做一个 Android App,前端用的是 Vue3 Quasar,打包交给 Capacitor 去跑在手机的 WebView 里,后端是 FastAPI 提供接口。开发模式下一切顺利,浏览器里访问接口没有任何问题,我甚至觉得打…