c++ 贪心算法

概念

贪心算法是一种在每一步选择中都选择当前最优解的算法策略。这种方法适用于某些特定问题,可以通过局部最优选择构建全局最优解。

特点

  1. 局部最优选择:每一步选择都选择当前看起来最优的解。
  2. 无后效性:当前选择不会影响未来选择的可能性。
  3. 可行性:必须确保每一步的选择是可行的。

优缺点

优点

  1. 简单易懂:贪心算法通常比其他算法(如动态规划)更简单,逻辑清晰,易于实现和理解。
  2. 高效:在适合的场景下,贪心算法通常具有较低的时间复杂度,能在较短时间内找到解。
  3. 节省空间:由于贪心算法在求解过程中不需要存储大量的中间结果,相对节省内存空间。
  4. 适用性广:对于一些特定类型的问题,贪心算法能够有效地找到全局最优解。

缺点

  1. 不适用于所有问题:贪心算法并不适用于所有问题,有些问题不能通过局部最优解得到全局最优解。
  2. 缺乏最优性保证:在某些情况下,贪心策略可能导致错误的结果,即找到的解不是最优解。例如,在 0-1 背包问题中,简单的贪心算法可能无法得到最优解。
  3. 难以分析:对于一些复杂的问题,判断贪心选择是否能导致全局最优解需要进行深入分析和证明。
  4. 局部最优陷阱:有时,贪心选择看似合理,但最终结果却不理想,导致程序错误或效率低下。

应用场景

  • 活动选择问题

  • 最小生成树

  • 单源最短路径

  • 背包问题

  • Huffman 编码

活动选择问题

问题描述:给定一组活动,选择不重叠的活动以最大化活动数量。

#include <iostream>
#include <vector>
#include <algorithm>struct Activity {int start;int end;
};bool compare(Activity a1, Activity a2) {return a1.end < a2.end;
}void activitySelection(std::vector<Activity>& activities) {std::sort(activities.begin(), activities.end(), compare);std::cout << "选择的活动: \n";int lastEndTime = -1;for (const auto& activity : activities) {if (activity.start >= lastEndTime) {std::cout << "活动(" << activity.start << ", " << activity.end << ")\n";lastEndTime = activity.end;}}
}int main() {std::vector<Activity> activities = {{1, 3}, {2, 5}, {4, 6}, {6, 7}, {5, 8}, {8, 9}};activitySelection(activities);return 0;
}

最小生成树(Kruskal 算法)

问题描述:给定一个带权无向图,找到最小生成树。

#include <iostream>
#include <vector>
#include <algorithm>struct Edge {int src, dest, weight;
};bool compare(Edge e1, Edge e2) {return e1.weight < e2.weight;
}class DisjointSet {
public:DisjointSet(int n) : parent(n), rank(n, 0) {for (int i = 0; i < n; ++i) parent[i] = i;}int find(int u) {if (u != parent[u])parent[u] = find(parent[u]);return parent[u];}void unionSets(int u, int v) {int rootU = find(u);int rootV = find(v);if (rootU != rootV) {if (rank[rootU] < rank[rootV]) {parent[rootU] = rootV;} else if (rank[rootU] > rank[rootV]) {parent[rootV] = rootU;} else {parent[rootV] = rootU;rank[rootU]++;}}}
private:std::vector<int> parent;std::vector<int> rank;
};void kruskal(int n, std::vector<Edge>& edges) {std::sort(edges.begin(), edges.end(), compare);DisjointSet ds(n);std::cout << "最小生成树的边:\n";for (const auto& edge : edges) {if (ds.find(edge.src) != ds.find(edge.dest)) {ds.unionSets(edge.src, edge.dest);std::cout << edge.src << " - " << edge.dest << " (权重: " << edge.weight << ")\n";}}
}int main() {int n = 4; // 顶点数std::vector<Edge> edges = {{0, 1, 10}, {0, 2, 6}, {0, 3, 5},{1, 3, 15}, {2, 3, 4}};kruskal(n, edges);return 0;
}

单源最短路径(Dijkstra 算法)

问题描述:在带权图中,找到从源节点到其他所有节点的最短路径。

#include <iostream>
#include <vector>
#include <queue>
#include <climits>typedef std::pair<int, int> Pair; // (距离, 节点)void dijkstra(int src, const std::vector<std::vector<Pair>>& graph) {int n = graph.size();std::vector<int> dist(n, INT_MAX);dist[src] = 0;std::priority_queue<Pair, std::vector<Pair>, std::greater<Pair>> pq;pq.push({0, src}); // (距离, 节点)while (!pq.empty()) {int u = pq.top().second;pq.pop();for (const auto& edge : graph[u]) {int v = edge.first;int weight = edge.second;if (dist[u] + weight < dist[v]) {dist[v] = dist[u] + weight;pq.push({dist[v], v});}}}std::cout << "从源节点 " << src << " 到其他节点的最短路径:\n";for (int i = 0; i < n; ++i) {std::cout << "到节点 " << i << " 的距离: " << dist[i] << "\n";}
}int main() {std::vector<std::vector<Pair>> graph = {{{1, 1}, {2, 4}},{{2, 2}, {3, 6}},{{3, 3}},{}};dijkstra(0, graph);return 0;
}

0-1 背包问题(动态规划与贪心结合)

问题描述:给定一组物品,每个物品有重量和价值,目标是最大化背包内物品的总价值。

#include <iostream>
#include <vector>
#include <algorithm>struct Item {int value;int weight;
};bool compare(Item a, Item b) {return (double)a.value / a.weight > (double)b.value / b.weight;
}double fractionalKnapsack(std::vector<Item>& items, int capacity) {std::sort(items.begin(), items.end(), compare);double totalValue = 0.0;for (const auto& item : items) {if (capacity == 0) break;if (item.weight <= capacity) {capacity -= item.weight;totalValue += item.value;} else {totalValue += item.value * ((double)capacity / item.weight);capacity = 0;}}return totalValue;
}int main() {std::vector<Item> items = {{60, 10}, {100, 20}, {120, 30}};int capacity = 50;double maxValue = fractionalKnapsack(items, capacity);std::cout << "最大价值: " << maxValue << "\n";return 0;
}

Huffman 编码

问题描述:给定一组字符及其频率,构建最优的前缀编码。

#include <iostream>
#include <queue>
#include <unordered_map>
#include <vector>struct Node {char ch;int freq;Node* left;Node* right;Node(char character, int frequency) : ch(character), freq(frequency), left(nullptr), right(nullptr) {}
};struct Compare {bool operator()(Node* l, Node* r) {return l->freq > r->freq;}
};void printCodes(Node* root, std::string str) {if (!root) return;if (!root->left && !root->right) {std::cout << root->ch << ": " << str << "\n";}printCodes(root->left, str + "0");printCodes(root->right, str + "1");
}void huffmanCoding(const std::unordered_map<char, int>& freqMap) {std::priority_queue<Node*, std::vector<Node*>, Compare> minHeap;for (const auto& pair : freqMap) {minHeap.push(new Node(pair.first, pair.second));}while (minHeap.size() > 1) {Node* left = minHeap.top(); minHeap.pop();Node* right = minHeap.top(); minHeap.pop();Node* newNode = new Node('$', left->freq + right->freq);newNode->left = left;newNode->right = right;minHeap.push(newNode);}Node* root = minHeap.top();std::cout << "Huffman 编码:\n";printCodes(root, "");
}int main() {std::unordered_map<char, int> freqMap = {{'a', 5}, {'b', 9}, {'c', 12}, {'d', 13}, {'e', 16}, {'f', 45}};huffmanCoding(freqMap);return 0;
}

总结

贪心算法虽然简单易懂,但并不是所有问题都适用。在实现贪心算法时,需要确保每一步的局部选择能够导向全局最优解。

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

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

相关文章

硬件常识

目录 示波器用万用表测三极管端子 示波器 示波器的夹子 鳄鱼夹接 负 钩子 接正 用万用表测三极管端子 (万用表调至二极管档/蜂鸣档) 测NPN三极管 先找到基级对应的引脚(红表笔接在基级时&#xff0c;黑表笔接在其他任一端子都有导通电压)集电结导通电压略大于发射结 (因为发…

Java 入门

目录 Java简介 Java JDK开发环境配置 第一个Java程序 Java标识符与关键字 Java注释 Java常量 Java变量的定义和使用 Java简介 Java简介&#xff1a; Java是由Sun Microsystems公司于1995年推出的一门面向对象的高级程序设计语言&#xff0c;可以运行于多个平台&#xff0c;其…

CSS--两列网页布局,三列布局和多行多列布局

两列网页布局 两列网页布局实验 先将一个未运用浮动效果的网页结构写出来 <style>header{/* 给页眉设置宽高和样式 */width:1000px;height: 40px;background-color: gray;border: 3px brown solid;margin-bottom: 5px;}article{width:1000px;height: 600px;background-c…

开源与商业的碰撞TPFLOW与Gadmin低代码的商业合作

随着数字化转型的浪潮席卷全球&#xff0c;企业对于高效、灵活的软件开发需求愈发迫切。低代码开发平台应运而生&#xff0c;为企业提供了简化开发流程、缩短开发周期的解决方案。在众多低代码开发平台中&#xff0c;Gadmin企业级低代码平台、TPFLOW工作流和SFDP超级表单脱颖而…

Edge浏览器提示“无法安全下载”

Edge浏览器在下载某些文件时&#xff0c;会提示“无法安全下载”。 注意事项&#xff1a;如果确实需要下载该文件&#xff0c;首先核对网址&#xff0c;确保下载文件的安全性&#xff0c;并在下载完成后进行必要的病毒查杀。 解决方法&#xff1a; 点击右侧的3个点&#xff0…

能通过Ping命令访问CentOS 9 Stream,但在使用Xshell连接

能通过Ping命令访问CentOS 9 Stream&#xff0c;但在使用Xshell进行SSH连接失败 1. **确认SSH服务状态**&#xff1a;2. **检查SSH配置**&#xff1a;要检查和设置PermitRootLogin选项&#xff0c;您需要编辑SSH配置文件/etc/ssh/sshd_config。以下是具体步骤&#xff1a;1. 打…

微服务系列三:微服务核心——网关路由

目录 前言 一、登录存在的问题归纳 二、*微服务网关整体方案 三、认识微服务网关 四、网关鉴权实现 五、OpenFeign微服务间用户标识信息传递实现 六、微服务网关知识追问巩固 前言 本篇文章具体讲解微服务中网关的实现逻辑、用于解决什么样的问题。其中标题中标注* 涉…

【经验分享】EasyExcel实现自定义动态化导出excel

需求&#xff1a; 需求涉及保存设备的灵活属性&#xff0c;设备的属性并不固定。允许设备的属性动态扩展。最终数据库采用EAV 模型的设计模式&#xff0c;使用三张表实现&#xff1a;设备表 、属性定义表、属性值表。 现在堆上述数据进行导入和导出。 解决&#xff1a; 这里使…

Docker入门系列——网络

Docker 通过容器化应用程序&#xff0c;彻底改变了我们构建、分发和运行应用程序的方式。然而&#xff0c;有效使用 Docker 的一个关键方面是理解容器如何相互通信以及与外界通信。 1. 什么是 Docker 网络&#xff1f; Docker 网络允许容器相互通信以及与外部资源通信。默认情况…

2024年大厂AI大模型面试题精选与答案解析

前言 随着AI市场&#xff0c;人工智能的爆火&#xff0c;在接下来的金九银十招聘高峰期&#xff0c;各大科技巨头和国有企业将会对AGI人才的争夺展开一场大战&#xff0c;为求职市场注入了新的活力。 为了助力求职者在面试中展现最佳状态&#xff0c;深入理解行业巨头的选拔标…

Nico,从零开始干掉Appium,移动端自动化测试框架实现

开头先让我碎碎念一波~去年差不多时间发布了一篇《 UiAutomator Nico&#xff0c;一个基于纯 adb 命令实现的安卓自动化测试框》&#xff08;https://testerhome.com/topics/37042&#xff09;&#xff0c; 由于种种原因 (详见此篇帖子) 当时选择了用纯 adb 命令来实现安卓自动…

RTP和RTCP的详细介绍及其C代码示例

RTP和RTCP的详细介绍及其C代码示例 RTP和RTCP简介RTP协议详解RTCP协议详解RTP和RTCP之间的关系C代码示例RTP和RTCP简介 RTP(Real-time Transport Protocol,实时传输协议)和RTCP(Real-time Transport Control Protocol,实时传输控制协议)是流媒体传输中常用的两个协议。R…

国内能用的Docker镜像源【2024最新持续更新】

国内能用的Docker镜像源【2024最新持续更新】 Docker 镜像加速列表&#xff08;2024年11月已更新&#xff09;配置方式1&#xff1a;临时使用配置方式2&#xff1a;长久有效 在国内使用 Docker 的朋友们&#xff0c;可能都遇到过配置镜像源来加速镜像拉取的操作。然而&#xff…

MySQL 的 select * 会用到事务吗?

我们都知道&#xff0c;在InnoDB存储引擎中&#xff0c;所有的修改操作都必须在事务中进行的。 那么&#xff0c;而 SELECT * 这种普通的读取操作其实也会在事务的上下文中执行&#xff0c;即使没有明确的开启事务语句InnoDB存储引擎也会为查询自动开启一个隐式事务。 因此&a…

队列(Queue)的介绍与实现

文章目录 队列队列的概念及结构 队列的实现初始化队列销毁队列队尾入队列队头出队列获取队列头部元素检测队列是否为空获取队列中有效元素个数 队列 队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表。队列遵…

3.1 快速启动Flink集群

文章目录 1. 环境配置2. 本地启动3. 集群启动4. 向集群提交作业4.1 提交作业概述4.2 添加打包插件4.3 将项目打包4.4 在Web UI上提交作业4.5 命令行提交作业 在本实战中&#xff0c;我们将快速启动Apache Flink 1.13.0集群&#xff0c;并在Hadoop集群环境中提交作业。首先&…

[sa-token]StpUtil.getLoginId

闲聊 一般情况下&#xff0c;我们想用uid&#xff0c;可能需要前端将uid传过来&#xff0c;或者将token传来&#xff0c;然后我们进行识别。 用了sa-token之后&#xff0c;可以使用StpUtil.getLoginId()方法获取当前会话的用户id 代码展示 例如以下代码&#xff1a; public Res…

算法实现 - 快速排序(Quick Sort) - 理解版

文章目录 算法介绍算法分析核心思想三个版本运行过程挖坑法Hoare 原版前后指针法 算法稳定性和复杂度稳定性时间复杂度平均情况O(nlogn)最差情况O( n 2 n^2 n2) 空间复杂度 算法介绍 快速排序是一种高效的排序算法&#xff0c;由英国计算机科学家C. A. R. Hoare在1960年提出&a…

算法【Java】—— 动态规划之斐波那契数列模型

动态规划 动态规划的思路一共有五个步骤&#xff1a; 状态表示&#xff1a;由经验和题目要求得出&#xff0c;这个确实有点抽象&#xff0c;下面的题目会带大家慢慢感受状态标识状态转移方程初始化&#xff1a;避免越界访问 dp 表&#xff0c;所以在进行填表之前我们要预先填…

03:选择语句的练习

选择语句的练习 1、分数判断2、判断年份3、判断水仙花数 1、分数判断 输入分数判断为&#xff1a;不及格(0 ≤ x <60)&#xff0c;一般(60 ≤ x < 75)&#xff0c;良好(75 ≤ x < 85)&#xff0c;优秀(85 ≤ x ≤ 99)&#xff0c;满分(100)。 #include <stdio.h&g…