【算法笔记】贪心算法

一、什么是贪心算法?

贪心算法是一种在每一步选择中都采取当前看起来最优(最“贪心”)的策略,从而希望得到全局最优解的算法设计思想。

  • 核心思想:每一步都做出局部最优选择,不回退。
  • 适用场景:问题具有最优子结构且满足贪心选择性质 —— 即局部最优可以导出全局最优。

二、贪心算法的典型流程

  1. 排序/预处理:对待选元素进行必要的排序或组织。
  2. 局部选择:按照某种规则(如最大收益、最小代价等)依次选取元素。
  3. 可行性检验:检查当前选择是否满足约束。
  4. 解的构造:在每次选择的基础上逐步构建最终解。

三、经典例题回顾

1. 活动选择问题

  • 题目:有 n n n 个活动,每个活动有开始时间 s i s_i si 和结束时间 f i f_i fi,要求选出最多互不冲突的活动集合。
  • 贪心策略:按活动结束时间从小到大排序,每次选取结束最早且与当前已选活动不冲突的活动。

2. 分数背包问题(Fractional Knapsack)

  • 题目:有 n n n 件物品,每件物品重量 w i w_i wi,价值 v i v_i vi,背包容量 W W W。物品可分割装入。
  • 贪心策略:按单位重量价值 v i w i \frac{v_i}{w_i} wivi 从大到小装入;装不下时装入尽可能多的部分。

3. 最小生成树(Kruskal 算法)

  • 题目:给定带权无向图,求一棵权值之和最小的生成树。
  • 贪心策略:对所有边按权值从小到大排序,依次加入不会形成环的最小边。

四、实战题目 —— 给 n n n 个国家加税

4.1 题目描述

  • n n n 个国家,初始关税税率均为 100%。
  • 对第 i i i 个国家,加税一次可将其税率提升 p i % p_i\% pi%(即税率从上一次的值再加上 p i p_i pi 百分点)。
  • 允许一共进行 k k k 次加税操作,每次只能选择一个国家进行一次加税。
  • 求经过 k k k 次加税后,所有国家税率的累乘(乘积)的最大值。

示例

输入:n = 3, p = [2, 5, 3], k = 4  
输出:最大乘积(按百分比计算)

4.2 贪心思路分析

收益定义
  • 对第 i i i 个国家当前税率 t i t_i ti(最开始 t i = 100 % t_i=100\% ti=100%)再加一次 p i % p_i\% pi%,其新的税率为 t i + p i t_i + p_i ti+pi
  • 在乘积中,相当于将当前乘积乘以 t i + p i t i \frac{t_i + p_i}{t_i} titi+pi,因此这次操作对总乘积的放大倍数为:

r i = t i + p i t i = 1 + p i t i r_i = \frac{t_i + p_i}{t_i} = 1 + \frac{p_i}{t_i} ri=titi+pi=1+tipi

  • 要使乘积最大,每次都应选择能带来最大放大倍数 r i r_i ri 的国家。
优先队列实现
  • 使用一个最大堆(priority_queue)存储每个国家当前可获得的放大倍数 r i r_i ri
  • 每次取出堆顶( r i r_i ri 最大的国家),实施一次加税:
    1. 更新该国家税率: t i ← t i + p i t_i \leftarrow t_i + p_i titi+pi
    2. 计算新的放大倍数: r i ← 1 + p i t i r_i \leftarrow 1 + \frac{p_i}{t_i} ri1+tipi
    3. 将更新后的 r i r_i ri 重新压入堆中。
  • 重复上述过程 k k k 次,结束后遍历所有国家税率,计算乘积。

4.3 代码示例(C++)

#include <bits/stdc++.h>
using namespace std;int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int n, k;cin >> n >> k;vector<double> p(n), t(n, 100.0);for (int i = 0; i < n; i++) {cin >> p[i];}// 优先队列:pair<放大倍数, 国家索引>auto cmp = [](const pair<double,int>& a, const pair<double,int>& b) {return a.first < b.first;};priority_queue<pair<double,int>, vector<pair<double,int>>, decltype(cmp)> pq(cmp);// 初始化for (int i = 0; i < n; i++) {double r = 1.0 + p[i] / t[i];pq.push({r, i});}// 执行 k 次加税while (k--) {auto [r, i] = pq.top(); pq.pop();t[i] += p[i];r = 1.0 + p[i] / t[i];pq.push({r, i});}// 计算累乘结果double ans = 1.0;for (double tax : t) {ans *= tax / 100.0;}cout << fixed << setprecision(6) << ans << "\n";return 0;
}

4.4 复杂度分析

  • 每次操作:弹出堆顶 + 插入堆顶,各 O ( log ⁡ n ) O(\log n) O(logn)
  • 总共 k k k 次操作,时间复杂度为: O ( k log ⁡ n ) O(k \log n) O(klogn)
  • 空间复杂度:需要存储 n n n 个国家的信息,为 O ( n ) O(n) O(n)

五、更多贪心练习题推荐

  1. 区间染色问题:给定区间集合,最少使用多少种颜色使重叠区间不同色?
  2. 跳跃游戏 II:每格有最大跳跃长度,求最少跳跃次数到达末尾。
  3. 分配饼干:孩子有满足度,饼干有大小,如何让最多孩子满足?
  4. 连通区间合并:给一堆区间,合并所有重叠区间,输出不重叠区间集合。

六、小结

  • 贪心算法以“当前最优选择”逐步构建解,适合于“最优子结构”且满足“贪心选择性质”的问题。
  • 真正的难点在于如何证明局部最优能导出全局最优,以及如何设计合适的贪心策略
  • 通过上述“加税”题,以及经典例题的练习,可以加深对贪心算法的理解与应用。

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

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

相关文章

现代c++获取linux所有的网络接口名称

现代c获取linux所有的网络接口名称 前言一、在linux中查看网络接口名称二、使用c代码获取三、验证四、完整代码如下五、总结 前言 本文介绍一种使用c获取本地所有网络接口名称的方法。 一、在linux中查看网络接口名称 在linux系统中可以使用ifconfig -a命令列举出本机所有网络…

打印及判断回文数组、打印N阶数组、蛇形矩阵

打印回文数组 1 1 1 1 1 1 2 2 2 1 1 2 3 2 1 1 2 2 2 1 1 1 1 1 1方法1&#xff1a; 对角线对称 左上和右下是对称的。 所以先考虑左上打印&#xff0c; m i n ( i 1 , j 1 ) \text min(i1,j1) min(i1,j1)&#xff0c;打印出来&#xff1a; 1 1 1 1 1 2 2 2 1 2 3 3 1 2 …

详解UnityWebRequest类

什么是UnityWebRequest类 UnityWebRequest 是 Unity 引擎中用于处理网络请求的一个强大类&#xff0c;它可以让你在 Unity 项目里方便地与网络资源进行交互&#xff0c;像发送 HTTP 请求、下载文件等操作都能实现。下面会详细介绍 UnityWebRequest 的相关内容。 UnityWebRequ…

UE5 在旋转A的基础上执行旋转B

用径向slider实现模型旋转时&#xff0c;得到的结果与ue编辑器里面的结果有很大出入。 问题应该是 两个FRotator&#xff08;0&#xff0c;10&#xff0c;0&#xff09;和&#xff08;10&#xff0c;20&#xff0c;30&#xff09;&#xff0c; 两个FRotator的加法结果为&…

4.2 Prompt工程与任务建模:高效提示词设计与任务拆解方法

提示词工程&#xff08;Prompt Engineering&#xff09;和任务建模&#xff08;Task Modeling&#xff09;已成为构建高效智能代理&#xff08;Agent&#xff09;系统的核心技术。提示词工程通过精心设计的自然语言提示词&#xff08;Prompts&#xff09;&#xff0c;引导大型语…

MySQL 索引的最左前缀匹配原则是什么?

MySQL 索引的最左前缀匹配原则详解 最左前缀匹配原则&#xff08;Leftmost Prefix Principle&#xff09;是 MySQL 复合索引&#xff08;联合索引&#xff09;查询优化中的核心规则&#xff0c;理解这一原则对于高效使用索引至关重要。 核心概念 定义&#xff1a;当查询条件…

SQL命令

一、控制台中查询命令 默认端口号&#xff1a;3306 查看服务器版本: mysql –version 启动MySQL服务&#xff1a;net start mysql 登录数据库&#xff1a;mysql -u root -p 查看当前系统下的数据库&#xff1a;show databases&#xff1b; 创建数据库&#xff1a;create…

新增 29 个专业,科技成为关键赛道!

近日&#xff0c;教育部正式发布《普通高等学校本科专业目录&#xff08;2025年&#xff09;》&#xff0c;新增 29 个本科专业&#xff0c;包括区域国别学、碳中和科学与工程、海洋科学与技术、健康与医疗保障、智能分子工程、医疗器械与装备工程、时空信息工程、国际邮轮管理…

零基础上手Python数据分析 (23):NumPy 数值计算基础 - 数据分析的加速“引擎”

写在前面 —— 超越原生 Python 列表,解锁高性能数值计算,深入理解 Pandas 的底层依赖 在前面一系列关于 Pandas 的学习中,我们已经领略了其在数据处理和分析方面的强大威力。我们学会了使用 DataFrame 和 Series 来高效地操作表格数据。但是,你是否好奇,Pandas 为何能够…

Android 13.0 MTK Camera2 设置默认拍照尺寸功能实现

Android 13.0 MTK Camera2 设置默认拍照尺寸功能实现 文章目录 需求&#xff1a;参考资料架构图了解Camera相关专栏零散知识了解部分相机源码参考&#xff0c;学习API使用&#xff0c;梳理流程&#xff0c;偏应用层Camera2 系统相关 修改文件-修改方案修改文件&#xff1a;修改…

HarmonyOS 框架基础知识

参考文档&#xff1a;HarmonyOS开发者文档 第三方库&#xff1a;OpenHarmony三方库中心仓 基础特性 Entry&#xff1a;关键装饰器 Components&#xff1a;组件 特性EntryComponent​​作用范围仅用于页面入口可定义任意可复用组件​​数量限制​​每个页面有且仅有一个无数量…

前端分页与瀑布流最佳实践笔记 - React Antd 版

前端分页与瀑布流最佳实践笔记 - React Antd 版 1. 分页与瀑布流对比 分页&#xff08;Pagination&#xff09;瀑布流&#xff08;Infinite Scroll&#xff09;展示方式按页分批加载&#xff0c;有明确页码控件滚动到底部时自动加载更多内容&#xff0c;无明显分页用户控制用…

Linux网络编程:TCP多进程/多线程并发服务器详解

Linux网络编程&#xff1a;TCP多进程/多线程并发服务器详解 TCP并发服务器概述 在Linux网络编程中&#xff0c;TCP服务器主要有三种并发模型&#xff1a; 多进程模型&#xff1a;为每个客户端连接创建新进程多线程模型&#xff1a;为每个客户端连接创建新线程I/O多路复用&am…

详解springcloudalibaba采用prometheus+grafana实现服务监控

文章目录 1.官网下载安装 prometheus和grafana1.promethus2.grafana 2. 搭建springcloudalibaba集成prometheus、grafana1. 引入依赖,springboot3.2之后引入如下2. 在yml文件配置监控端点暴露配置3. 在当前启动的应用代码中添加&#xff0c;在prometheus显示的时候附加当前应用…

数据分析1

一、常用数据处理模块Numpy Numpy常用于高性能计算&#xff0c;在机器学习常常作为传递数据的容器。提供了两种基本对象&#xff1a;ndarray、ufunc。 ndarray具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。 ufunc提供了对数组快速运算的标准数学函数。 ndar…

DeepSeek智能时空数据分析(六):大模型NL2SQL绘制城市之间连线

序言&#xff1a;时空数据分析很有用&#xff0c;但是GIS/时空数据库技术门槛太高 时空数据分析在优化业务运营中至关重要&#xff0c;然而&#xff0c;三大挑战仍制约其发展&#xff1a;技术门槛高&#xff0c;需融合GIS理论、SQL开发与时空数据库等多领域知识&#xff1b;空…

2023ICPC合肥题解

文章目录 F. Colorful Balloons(签到)E. Matrix Distances(思维小结论)J. Takeout Delivering(最短路)G. Streak Manipulation(二分dp)C. Cyclic Substrings(回文自动机) 题目链接 F. Colorful Balloons(签到) int n;cin>>n;for(int i1;i<n;i) cin>>s[i];map<…

数字技术驱动下教育生态重构:从信息化整合到数字化转型的路径探究

一、引言 &#xff08;一&#xff09;研究背景与问题提出 在当今时代&#xff0c;数字技术正以前所未有的速度和深度渗透到社会的各个领域&#xff0c;教育领域也不例外。从早期的教育信息化整合到如今的数字化转型&#xff0c;教育系统正经历着一场深刻的范式变革。 回顾教…

terraform 动态块(Dynamic Blocks)详解与实践

在 Terraform 中&#xff0c;动态块&#xff08;Dynamic Blocks&#xff09; 是一种强大的机制&#xff0c;允许你根据变量或表达式动态生成配置块&#xff0c;避免重复编写相似的代码。这在处理需要重复定义的结构&#xff08;如资源参数、嵌套配置&#xff09;时特别有用。以…

Unity3D引擎框架及用户接口调用方式相关分析及汇总

分析目的 目前外网3D手游绝大部基于Unity3D引擎进行开发,Unity3D引擎属于商业引擎,引擎整理框架的运行机制较为神秘,本文介绍Unity引擎框架、对象组织方式、用户接口与引擎交互方式等原理,通过本文的分析和介绍可了解Unity3D框架中大致执行原理。 实现原理 Unity引擎作为…