c++ 贪心算法
概念
贪心算法是一种在每一步选择中都选择当前最优解的算法策略。这种方法适用于某些特定问题,可以通过局部最优选择构建全局最优解。
特点
- 局部最优选择:每一步选择都选择当前看起来最优的解。
- 无后效性:当前选择不会影响未来选择的可能性。
- 可行性:必须确保每一步的选择是可行的。
优缺点
优点
- 简单易懂:贪心算法通常比其他算法(如动态规划)更简单,逻辑清晰,易于实现和理解。
- 高效:在适合的场景下,贪心算法通常具有较低的时间复杂度,能在较短时间内找到解。
- 节省空间:由于贪心算法在求解过程中不需要存储大量的中间结果,相对节省内存空间。
- 适用性广:对于一些特定类型的问题,贪心算法能够有效地找到全局最优解。
缺点
- 不适用于所有问题:贪心算法并不适用于所有问题,有些问题不能通过局部最优解得到全局最优解。
- 缺乏最优性保证:在某些情况下,贪心策略可能导致错误的结果,即找到的解不是最优解。例如,在 0-1 背包问题中,简单的贪心算法可能无法得到最优解。
- 难以分析:对于一些复杂的问题,判断贪心选择是否能导致全局最优解需要进行深入分析和证明。
- 局部最优陷阱:有时,贪心选择看似合理,但最终结果却不理想,导致程序错误或效率低下。
应用场景
-
活动选择问题
-
最小生成树
-
单源最短路径
-
背包问题
-
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;
}
总结
贪心算法虽然简单易懂,但并不是所有问题都适用。在实现贪心算法时,需要确保每一步的局部选择能够导向全局最优解。
相关文章:
c++ 贪心算法
概念 贪心算法是一种在每一步选择中都选择当前最优解的算法策略。这种方法适用于某些特定问题,可以通过局部最优选择构建全局最优解。 特点 局部最优选择:每一步选择都选择当前看起来最优的解。无后效性:当前选择不会影响未来选择的可能性…...
15分钟学 Go 第 35 天:Go的性能调优 (7000字详细教程)
第35天:Go的性能调优 目标:理解Go语言中基本的性能优化,学习如何分析和提高Go程序的执行效率。 一、性能调优概述 性能调优是软件开发中的一个重要环节,它可以确保程序在资源有限的环境下高效运行。Go语言天生具备高效的性能表现…...
6、显卡品牌分类介绍:技嘉 - 计算机硬件品牌系列文章
技嘉科技是一家以主板、显卡在业界缔造无以撼动的地位的科技公司,其核心理念是「技术创新、质量稳定」的高标准。技嘉专注于关键技术研发,其经营范围涵盖家用、商用、电竞等多元科技领域。通过应用突破性的专利技术,技…...
Redis数据类型——针对实习面试
目录 Redis数据类型Redis常用的数据类型有哪些?String类型可以用于哪些场景?Set类型可以用于哪些场景?Bitmaps类型可以用于哪些场景?HyperLogLog类型可以用于哪些场景?Hash类型与Set类型有什么区别?Hash类型…...
roberta融合模型创新中文新闻文本标题分类
项目源码获取方式见文章末尾! 600多个深度学习项目资料,快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…...
《密码系统设计》实验二 4-6学时
文章目录 《密码系统设计》实验实验项目实验二 密码算法实现4-6 学时实践要求(30 分)1. 定义宏2. 使用特定的源文件3. 编译MIRACL库4. 配置KCM和Comba方法5. 编译和运行MEX工具6. 使用config.c工具总结1. 准备环境2. 下载和解压MIRACL库3. 定义宏4. 使用…...
Zypher Network:全栈式 Web3 游戏引擎,服务器抽象叙事的引领者
近期,《黑神话:悟空》的爆火不仅让 AAA 游戏重回焦点,也引发了玩家与开发者的热议。Web2 游戏的持续成功导致部分 Web3 玩家们的倒戈,对比之下 Web3 游戏存在生命周期短且商业模式难以明确的问题,尤其在当前加密市场环…...
2025生物发酵展(济南)为生物制造产业注入新活力共谱行业新篇章
2025第十四届国际生物发酵展将于3月3-5日济南盛大举办!产业链逐步完整,展会面积再创历史新高,展览面积较上届增涨至60000平方米,专业观众40000,品牌展商800,同期活动会议增加至50场,展会同期将举…...
git入门教程14:Git与其他工具的集成
一、Git与代码托管平台的集成 GitHub 集成方式: 在GitHub上创建或克隆仓库。在本地使用Git命令进行代码提交和推送(如git push)。GitHub提供Web界面进行代码浏览、协作和持续集成配置。 特点: 支持Pull Request,便于代…...
在Zetero中调用腾讯云API的输入密钥的问题
也是使用了Translate插件了,但是需要调用腾讯云翻译,一直没成功。 第一步就是,按照这上面方法做:百度、阿里、腾讯、有道各平台翻译API申请教程 之后就是:Zotero PDF translat翻译:申请腾讯翻译接口 主要是…...
【AD】1-8 AD24软件工程创建
1.点击文件,新建项目 2.如图进行设置工程名称和文件路径 3.创建原理图库及原理图,并保存 4.新建PCB库及PCB,并保存 5.单击右键工程保存 注意:先新建工程,在新建文件...
RT-Thread学习
文章目录 前言一、rtt的启动流程二、移植工作总结 前言 RT-Thread学习,这里记录对bsp的移植 一、rtt的启动流程 RT-Thread 支持多种平台和多种编译器,而 rtthread_startup() 函数是 RT-Thread 规定的统一启动入口。一般执行顺序是:系统先从…...
20241102在荣品PRO-RK3566开发板使用荣品预编译的buildroot通过iperf2测试AP6256的WIFI网速
20241102在荣品PRO-RK3566开发板使用荣品预编译的buildroot通过iperf2测试AP6256的WIFI网速 2024/11/2 14:18 客户端:荣耀手机HONOR 70【iPerf2 for Android】 服务器端:荣品PRO-RK3566开发板 预编译固件:update-pro-rk3566-buildroot-hdmi-2…...
网络模型——二层转发原理
网课地址:网络模型_二层转发原理(三)_哔哩哔哩_bilibili 一、路由交换 网络:用来信息通信,信息共享的平台。 网络节点(交换机,路由器,防火墙,AP)介质&#…...
【编程技巧】C++如何使用std::map管理std::function函数指针
一、问题背景 开发过程中遇到了需要根据const字符串调用不同函数的要求。在开发过程中为了快速实现功能,实际使用了if else等判断实现了不同函数的调用,徒增了不少代码行数。 明知道可以采用map管理函数指针,但是没有具体实现过,…...
导航栏小案例
实现类似于这样的效果 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>导航栏</title><style>*{margin: 0;padding: 0;}.div1{width: 100%;height: 60px;/* border: 1px solid blue; */background-color:rgb(…...
MyBatis一文入门精通,面试题(含答案)
一、MyBatis详细介绍 MyBatis 是一个流行的 Java 持久层框架,主要用于简化 SQL 数据库操作。它的设计初衷是通过 XML 或注解的方式配置和执行 SQL 语句,使得数据库操作更加灵活、方便和高效。相比于传统的 JDBC,MyBatis 提供了一些关键优势&…...
Ubuntu18.04服务器非root用户在虚拟环境下的python版本设定
最近需要跑一个python3.9.16版本的代码,Ubuntu18.04服务器上是上次博客中已经定死的python3.8.0版本 需要创建一个虚拟环境,并且在虚拟环境中配置python3.9.16版本 只需要创建一个虚拟环境 conda create -n yyy python3.9.16yyy是你的虚拟环境名字 创建…...
CodeS:构建用于文本到 SQL 的开源语言模型
发布于:2024 年 10 月 29 日 #RAG #Text2 SQL #NL2 SQL 语言模型在将自然语言问题转换为 SQL 查询(文本到 SQL )的任务中显示出良好的性能。然而,大多数最先进的 (SOTA) 方法都依赖于强大但闭源的大型语言…...
HTML 基础概念:什么是 HTML ? HTML 的构成 与 HTML 基本文档结构
文章目录 什么是 HTML ?HTML 的构成 ?什么是 HTML 元素?HTML 元素的组成部分HTML 元素的特点 HTML 基本文档结构如何打开新建的 HTML 文件代码查看 什么是 HTML ? HTML(超文本标记语言,HyperText Markup L…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
李沐--动手学深度学习--GRU
1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀”
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀” 在JavaScript中,我们经常需要处理文本、数组、对象等数据类型。但当我们需要处理文件上传、图像处理、网络通信等场景时,单纯依赖字符串或数组就显得力不从心了。这时ÿ…...
深入理解 C++ 左值右值、std::move 与函数重载中的参数传递
在 C 编程中,左值和右值的概念以及std::move的使用,常常让开发者感到困惑。特别是在函数重载场景下,如何合理利用这些特性来优化代码性能、确保语义正确,更是一个值得深入探讨的话题。 在开始之前,先提出几个问题&…...
