【信奥一本通提高篇】基础算法之贪心算法
原文
https://bbs.fmcraft.top/blog/index.php/archives/22/
贪心算法
概述
近年来的信息学竞赛试题,经常出现求一个问题的可行解或最优解的题目。这类问题就是我们通常所说的最优化问题。贪心算法是求解这类问题的一种常用算法。在众多的算法中,贪心算法可以算得上是最接近人们日常思维的一种算法,常被信息学奥赛选手用来求解一些数据规模很大的问题。
一、贪心算法
贪心算法是从问题的初始状态出发,通过若干次的贪心选择而得到的最优值(或较优值)的一种求解问题策略,即贪心策略。
换句话说,贪心策略是一种在每次决策时采取当前意义下最优策略的算法,做出的选择只是在某种约束条件下的局部最优解或较优解,并不一定是全局的最优解或较优解。不过,某些特定的问题是可以利用贪心算法求得其最优解或较优解的。
【引例1】在N行M列的正整数矩阵中,要求从每行中选出一个数,使得选出的N个数的和最大。
分析:本题可以用贪心算法求解。选N次,每一次选出相应行中的最大值即可。
【引例2】在一个N×M的方格阵中,每一格子赋予一个数(即权值),规定每次移动时只能向上或向右。现试找出一条路径,使其从左下角至右上角所经过的权值之和最大。
我们以2×3的矩阵为例:
| / | 列1 | 列2 | 列3 |
|---|---|---|---|
| 行1 | 3 | 4 | 6 |
| 行2 | 1 | 2 | 10 |
| 若按贪心算法求解,所得路径为:1→3→4→6。 | |||
| 若按动态规划求解,所得路径为:1→2→ 10→6。 | |||
| 显然,这里用贪心算法求解,得到的并不是问题的最优解。 |
二、贪心算法的特点
1.贪心选择
所谓贪心选择是指应用同一规则,将原问题变为一个相似的但规模更小的子问题,而后的每 一步都是当前看似最佳的选择,且这种选择只依赖于已做出的选择,不依赖于未做出的选择。
最优子结构
执行算法时,每一次得到的结果虽然都是当前问题的最优解(即局部最优解),但只有满足全 局最优解包含局部最优解时,才能保证最终得到的结果是最优解。
三、几个简单的贪心实例
1.最优装载问题
给 n 个物体,第i个物体重量为W₁, 选择尽量多的物体,使得总重量不超过C。
【思路点拨】
由于只关心物体的数量,所以装重的没有装轻的划算。只需把所有物体按重量从小到大排 序,依次选择每个物体,直到装不下为止。这就是一种典型的贪心算法,它只顾眼前,但却能得到全 局最优解。
贪心策略:先装最轻的。
2.部分背包问题
有n 个物体,第i个物体的重量为w₁, 价值为 v₁,在总重量不超过C 的情况下让总价值尽量高。 每一个物体可以只取走一部分,价值和重量按比例计算。
【思路点拨】
本题是在上一题的基础上增加了价值项,所以不能简单地像上一题那样先选出轻的(轻的可 能其价值也小),也不能先拿价值大的(它可能特别重),而应该综合考虑两个因素。一种直观的贪心策略是:优先选出价值与重量的比值最大的,直到重量和正好为C。
注意:由于每个物体可以只选出一部分,因此一定可以让总重量恰好为C(或者所有物体全选,总重量还不足C), 而且除了最后一个以外,所有的物体要么不选,要么全部选。
贪心策略:先选出性价比高的。
3.乘船问题
有n个人,第i个人重量为w,。每艘船的载重量均为C,最多可乘两个人。求用最少的船装载所有人的方案。
【思路点拨】
考虑最轻的人i, 他应该和谁一起乘呢?如果每个人都不能和他一起乘,则只能每人乘一艘船。 否则,他应该选择能和他一起乘的人中最重的一个人j。这样的选择只是让“眼前”的浪费最少,因此它是一种贪心策略。
贪心策略:最轻的人和最重的人配对。
这个贪心策略的正确性和有效性是可以用反证法证明的。
证明:假设这个贪心策略不是最优的,最优方案中的i是什么样的呢?
情况1:i不和任何一个人乘同一艘船,那么可以把j拉过来和他一起乘,总船数不会增加(且可能会减少!),并且符合贪心策略。
情况2:i和另外一个人k同乘一艘船,其中k比j轻。把j和k交换后,j原来所在的船仍然不会超重(因为k比j轻),因此i和j同乘一艘船,所得到的新解不会更差,且符合贪心策略。
由此可见,利用本题的贪心策略求解不会丢失最优解。
程序实现。在前面的分析中,比j更重的人只能每人乘一艘船。这样,我们只需用两个指针i和j分别表示当前考虑的最轻的人和最重的人。每次先将指针j往左移动,直到i和j可以共乘一艘船,然后将指针i往右移,指针j往左移,并重复上述操作,直到所有的人都装载上。不难看出,这 个程序的时间复杂度仅为O(n), 是最优算法。
总结
通过以上3个例子,我们大致了解了贪心算法的形式和正确性证明的基本方法。下面,进一步分析几个经典贪心算法的应用,加深对贪心算法的理解。
四、贪心算法的经典应用
1.选择不相交区间问题
给定n个开区间(a,b),选择尽量多个区间,使得这些区间两两没有公共点。
【思路点拨】
首先,按照b_1<=b_2<=…<=b_n,的顺序排序,依次考虑各个区间,如果没有和已经选择的区间冲突,就选:否则就不选。
【正确性】
假设b_1<b_i且(a_j,b_j)、(a_i,b_i) 分别与之前的区间不冲突,当前选(a_j,b_j).若(a_j,b_j)与(a_j,b_i)不冲突,则还可以选择(a_i,b_i),答案个数加一;若(a_j,b_j)与(a_i,b_i)冲突,因为b_j<b_i,所以选(a_j,b_j)对以后的影响更小。
2.区间选点问题
【问题描述】
给定n个闭区间[a_i,b_i], 在数轴上选尽量少的点,使得每个区间内都至少有一个点(不同区同内含的点可以是同一个)。
【思路点拨】
首先按照区间的结束位置从小到大排序。然后从区间1到区间n 进行选择:对于当前区间,吾 集合中的数不能覆盖它,则将区间末尾的数加入集合。
贪心策略:取最后一个。
如图下图所示,如果选灰色点,则移动到黑色点会更优。

3.区间覆盖问题
【问题描述】
给n个闭区间[a_i,b_i],选择尽量少的区间覆盖一条指定的线段区间[s,t]。
【思路点拨】
将所有的区间按左端点从小到大排序,依次处理每个区间。每次选择覆盖点s的区间中右端 点坐标最大的一个,并将s更新为该区间的右端点坐标,直到选择的区间已包含了t为止。
贪心策略:在某个时刻的s, 找一个满足a[i]≤s的b[i]最大值即可。
4.流水作业调度问题
【问题描述】
有n个作业要在两台机器M1和M2组成的流水线上完成加工。每个作业i都必须先花时间a在M上加工,然后花时间b在M2上加工。
确定n个作业的加工顺序,使得从作业1在机器M1上加工开始到作业n在机器M2上加工实完为止所用的总时间最短。
【思路点拨】
直观上,最优调度一定让M1、M2的空闲时间尽量短。
Johnson算法:设N1为a<b的作业集合,N2 为a≥b的作业集合,将N1的作业按a非减序排序,N2中的作业按照b非增序排序,则N1作 业接N2作业构成最优顺序。
算法的程序易于实现,时间复杂度为O(nlogn),正确性需要证明。
5.带限期和罚款的单位时间任务调度
【问题描述】
有n个任务,每个任务都需要1个时间单位执行,任务i的截止时间d_i(1≤d≤n)表示要求任务i在时问d_i结束时必须完成,误时惩罚w_i表示若任务i未在时间d_i结束之前完成,将导致w_i的罚款。
确定所有任务的执行顺序,使得惩罚最少。
【思路点拨】
要使罚款最少.我们显然应尽量完成w[i]值较大的任务。
此时,我们可以将任务按w[i]从大到小进行排序,然后按照排好的顺序依次对任务进行安排。 安排的规则为:使处理任务i的时间既在d[i]之内,又尽量靠后;如果d[i]之内的时间都已经排满,就放弃处理此项任务。
【算法证明】
假设按照上述算法得到的解不是最优的,那么必然存在某个任务j应当安排到处理的过程中 但却没有安排。假设我们要将该任务安排进去,由于在时间d[j]内都已经排满,就必然需要将一个已安排的任务k与之替换,而w[k]≥w[j]。 这样,替换显然会增加罚款的数额、因此,除上还安排方法以外的安排方法都不会使罚款的数额减少,可知用上述算法得到的结果是最优的。
【实现方法】
①先按照罚款数额从大到小快排。
②顺序处理每个任务,若能安排,则找一个最晚时间:否则放在最后的空位上。
练习
如需练习学习的内容,可自行寻找相关题目。
也可以前往FMCRAFT OJ做题。下面的地址可以直接跳转到其相关题目一本通训练中的题单 算法训练中的题单。使用OJ前需要注册账户。
相关文章:
【信奥一本通提高篇】基础算法之贪心算法
原文 https://bbs.fmcraft.top/blog/index.php/archives/22/ 贪心算法 概述 近年来的信息学竞赛试题,经常出现求一个问题的可行解或最优解的题目。这类问题就是我们通常所说的最优化问题。贪心算法是求解这类问题的一种常用算法。在众多的算法中,贪心…...
PyQt6实例_批量下载pdf工具_批量pdf网址获取
目录 前置: 步骤: step one 安装包 step two 获取股票代码 step three 敲代码,实现 step four 网址转pdf网址 视频 前置: 1 本系列将以 “PyQt6实例_批量下载pdf工具”开头,放在 【PyQt6实例】 专栏 2 本节讲…...
KMeans算法案例
KMeans算法案例 案例介绍 已知:客户性别、年龄、年收入、消费指数 需求:对客户进行分析,找到业务突破口,寻找黄金客户 数据集共包含顾客的数据, 数据共有 4 个特征, 数据共有 200 条。接下来,使用聚类算法对具有相似…...
IDApro直接 debug STM32 MCU
使用IDA pro 逆向分析muc 固件的时候, 难免要进行一些动态的debug,来进一步搞清楚一些内存的数据、算法等,这时候使用远程debug 的方式直接在mcu上进行debug 最合适不过了。 不过有个前提条件就是一般来说有的mcu 会被运行中的代码屏蔽 RDP、…...
六十天前端强化训练之第三十六天之E2E测试(Cypress)大师级完整指南
欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗,谢谢大佬! 目录 一、知识讲解 1. E2E测试核心概念 2. Cypress框架特性 3. 工作原理 4. 测试金字塔定位 二、核心代码示例:用户登录全流程测试 三、实现效果展示 四、学习要…...
创建和管理Pod
创建和管理Pod 文章目录 创建和管理Pod[toc]一、什么是Pod1.Pod 的核心定义2.Pod 的组成与结构3.Pod 的生命周期4.Pod 的使用场景5.高级特性 二、Pod与容器1. 为什么使用 Pod 作为 Kubernetes 的最小部署单元?2. 单一容器 Pod3. 多容器 Pod4. 初始化容器(…...
20250330-傅里叶级数专题之离散傅里叶变换(5/6)
5. 傅里叶级数专题之离散傅里叶变换 推荐视频: 工科生以最快的速度理解离散傅立叶变换(DFT) 哔哩哔哩 20250328-傅里叶级数专题之数学基础(0/6)-CSDN博客20250330-傅里叶级数专题之傅里叶级数(1/6)-CSDN博客20250330-傅里叶级数专题之傅里叶变换(2/6)-CSDN博客20250330-傅里叶…...
Android设计模式之代理模式
一、定义: 为其他对象提供一种代理以控制对这个对象的访问。 二、角色组成: Subject抽象主题:声明真是主题与代理的共同接口方法,可以是一个抽象类或接口。 RealSubject真实主题:定义了代理表示的真实对象,…...
《非暴力沟通》第十二章 “重获生活的热情” 总结
《非暴力沟通》第十二章 “重获生活的热情” 的核心总结: 本章将非暴力沟通的核心理念延伸至生命意义的探索,提出通过觉察与满足内心深处的需要,打破“义务性生存”的桎梏,让生活回归由衷的喜悦与创造。作者强调,当行动…...
3.29:数据结构-绪论线性表-上
一、时间复杂度 1、ADT 2、定义法计算时间复杂度:统计核心语句的总执行次数 (1)例题1,与2022年的真题对比着写 此题关键在于求和公式的转化,类型为:线性循环嵌套非线性循环 2022年那道题如果考场上实在脑…...
Java项目如何打jar包?
1.java把项目打包成jar 步骤一、IDEA -> File -> Project Structure -> Artifacts -> -> JAR -> From moduls with dependencies... -> 选择 Module 和 Main Class -> 选择 JAR files from libraries JAR files from libraries 解释 extract to the t…...
【奶茶经济学的符号暴力本质】
金字塔式七层分析框架:奶茶经济学的符号暴力本质 第一层:缺货的戏剧经济学 结论:13.7%缺货率是精密计算的神经钩 机制:喜茶新品首日仅投放86.3%门店,制造"限量焦虑"激活前额叶决策区矛盾验证: …...
Python PDF解析利器:pdfplumber | AI应用开发
Python PDF解析利器:pdfplumber全面指南 1. 简介与安装 1.1 pdfplumber概述 pdfplumber是一个Python库,专门用于从PDF文件中提取文本、表格和其他信息。相比其他PDF处理库,pdfplumber提供了更直观的API和更精确的文本定位能力。 主要特点…...
大模型架构记录13【hr agent】
一 Function calling 函数调用 from dotenv import load_dotenv, find_dotenvload_dotenv(find_dotenv())from openai import OpenAI import jsonclient OpenAI()# Example dummy function hard coded to return the same weather # In production, this could be your back…...
conda 清除 tarballs 减少磁盘占用 、 conda rename 重命名环境、conda create -n qwen --clone 当前环境
🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️ 文章目录 conda clean --tarballsconda rename 重命名环境conda create -n qwen --clone …...
Java基础-24-继承-认识继承-权限修饰符-继承的特点
在Java中,继承是面向对象编程(OOP)的一个重要特性。通过继承,一个类可以复用另一个类的属性和方法,从而实现代码的重用性和扩展性。以下是关于继承的一些关键点,包括权限修饰符和继承的特点。 1. 继承的基本…...
Bootstrap 表格:高效布局与动态交互的实践指南
Bootstrap 表格:高效布局与动态交互的实践指南 引言 Bootstrap 是一个流行的前端框架,它为开发者提供了丰富的组件和工具,使得构建响应式、美观且功能丰富的网页变得更加简单。表格是网页中常见的元素,用于展示数据。Bootstrap 提供了强大的表格组件,可以帮助开发者轻松…...
pycharm相对路径引用方法
用于打字不方便,以下直接手写放图,直观理解...
新能源智慧灯杆的智能照明系统如何实现节能?
叁仟新能源智慧灯杆的智能照明系统可通过以下多种方式实现节能: 智能调光控制 光传感器技术:在灯杆上安装光传感器,实时监测周围环境的光照强度。当环境光线充足时,如白天或有其他强光源时,智能照明系统会自动降低路…...
Jenkins教程(自动化部署)
Jenkins教程(自动化部署) 1. Jenkins是什么? Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具,广泛用于项目开发,具有自动化构建、测试和部署等功能。Jenkins用Java语言编写,可在Tomcat等流行的servlet容器中运行&…...
行业智能体大爆发,分布式智能云有解
Manus的一夜爆红,在全球范围内引爆关于AI智能体的讨论。 与过去一般的AI助手不同,智能体(AI Agent)并非只是被动响应,而是主动感知、决策并执行的应用。Gartner预测,到2028年,15%的日常工作决策…...
日语Learn,英语再认识(5)
This is a dedicated function — it exists solely to solve this case. This is a dedicated function. It’s a dedicated method for solving this case. 其他备选词(但没dedicated精准): special → 含糊,有时只是“特别”…...
【区块链安全 | 第十四篇】类型之值类型(一)
文章目录 值类型布尔值整数运算符取模运算指数运算 定点数地址(Address)类型转换地址的成员balance 和 transfersendcall,delegatecall 和 staticcallcode 和 codehash 合约类型(Contract Types)固定大小字节数组&…...
音视频入门基础:MPEG2-TS专题(25)——通过FFmpeg命令使用UDP发送TS流
一、通过FFmpeg命令使用UDP发送TS流 通过以下FFmpeg命令可以将一个mp4文件转换为ts封装,并基于UDP发送(推流): ffmpeg.exe -re -i input.mp4 -vcodec copy -acodec copy -f mpegts udp://127.0.0.1:1234 其中: “in…...
Error in torch with streamlit
报错信息: This is the error which is a conflict between torch and streamlit: Examining the path of torch.classes raised: Tried to instantiate class path.path’, but it does not exist! Ensure that it is registered via torch::class Steps to reproduce: py…...
网络基础知识介绍
目录 一、计算机网络背景与发展 1.1 计算机网络的背景 编辑1.2 计算机网络的发展历程 二、网络协议 2.1 认识网络协议 2.3 协议分层 2.4 OSI七层模型 2.5 TCP/IP 五层(或四层)模型 三、网络传输基本流程 3.1 网络传输流…...
MIPS-32架构(寄存器堆,指令系统,运算器)
文章目录 0 Preview:寄存器32通用0 $zero1 $at2—3 \$v0-$v14—7 \$a0-$a38—15 \$t0-$t716—23 \$s0-$s724—25 \$t8-$t926—27 \$k0-$k128 $gp29 $sp30 $fp 指令系统运算存储器 0 Preview: MIPS架构有32位版本和64位版本,本文介绍32位版本 寄存器 正如笔者曾说…...
zip和tar.gz
本文来源: 在压缩文件格式选择上,zip和tar.gz有本质差异,主要体现在以下五个方面: 一、压缩机制不同 tar.gz是"两步走"方案:先用tar工具将多个文件/目录打包为单个未压缩的归档文件(保留权限…...
【什么是机器学习——多项式逼近】
什么是机器学习——多项式逼近 机器学习可以分成三大类别,监督学习、非监督学习、强化学习。三大类别背后的数学原理不同。监督学习使用了数学分析中的函数逼近方法和概率统计中的极大似然方法;非监督学习使用聚类和EM算法;强化学习使用马尔可夫决策过程的想法。 机器学习的…...
C++中的搜索算法实现
C中的搜索算法实现 在编程中,搜索算法是解决各种问题的基础工具之一。C作为一种功能强大的编程语言,提供了多种实现搜索算法的方式。本文将详细介绍两种常见的搜索算法:线性搜索和二分搜索,并通过代码示例展示它们的实现。 一、…...
