C++ 算法主题系列之贪心算法的贪心之术

作者:新兰2024.02.04 19:52浏览量:4

简介:本篇文章将深入探讨贪心算法的原理和应用,通过实例展示如何利用贪心策略解决实际问题。我们将一起探索贪心算法的奥秘,以及在C++中的实现方法。

贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。它是一种解决问题的策略,在每一步选择时都采取当前状态下的最优解,并希望通过这种方式能够获得全局的最优解。
贪心算法并不总是能够得到问题的最优解,但它通常可以给出相当好的结果。贪心算法的关键在于如何定义“贪心”和如何实现贪心选择。下面我们将通过几个实例来展示贪心算法的应用。
实例一:背包问题
背包问题是一个经典的优化问题,其中给定一组物品,每个物品都有自己的重量和价值,我们的目标是选择一些物品放入背包中,使得背包内物品的总价值最大,同时不超过背包的容量限制。
我们可以使用贪心算法来解决这个问题。首先,我们将物品按照单位重量价值(价值/重量)从大到小排序。然后,我们依次选择物品放入背包中,每次选择当前单位重量价值最高的物品,直到背包满或者所有物品都被选择完毕。
下面是一个使用C++实现的背包问题的贪心算法示例代码:

  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace std;
  5. struct Item {
  6. int weight;
  7. int value;
  8. };
  9. bool compare(Item& a, Item& b) {
  10. return (double)a.value/a.weight > (double)b.value/b.weight;
  11. }
  12. int knapsack(vector<Item>& items, int capacity) {
  13. sort(items.begin(), items.end(), compare); // 按单位重量价值从大到小排序
  14. int totalValue = 0;
  15. for (int i = 0; i < items.size(); i++) {
  16. if (items[i].weight <= capacity) { // 如果当前物品能装入背包
  17. capacity -= items[i].weight; // 更新背包容量
  18. totalValue += items[i].value; // 累加物品价值
  19. } else { // 如果当前物品无法装入背包,按比例装入部分物品
  20. totalValue += items[i].value * capacity / items[i].weight;
  21. break; // 跳出循环,不再选择其他物品
  22. }
  23. }
  24. return totalValue;
  25. }

这个示例代码中,我们定义了一个Item结构体来表示每个物品的重量和价值。然后我们使用贪心策略,按照单位重量价值的降序排列物品,并依次选择物品放入背包中,直到背包满或者所有物品都被选择完毕。最后返回背包内物品的总价值。
实例二:最小生成树问题
最小生成树问题是图论中的一个经典问题,其中给定一个带权重的连通图,我们需要选择一些边来连接所有顶点,使得所有顶点之间都有路径相连,并且边的总权重最小。
我们可以使用贪心算法来解决最小生成树问题。具体来说,我们可以使用Kruskal算法或Prim算法来实现贪心策略。Kruskal算法从边的集合中选择权重最小的边,并确保选择的边不会构成环;Prim算法从单个顶点开始,每次选择连接当前生成树和未生成树之间的权重最小的边,直到所有顶点都被包含在生成树中。
下面是一个使用C++实现的Prim算法的示例代码:
```cpp

include

include

include

using namespace std;
const int INF = 0x3f3f3f3f; // 无穷大值
vector graph[100]; // 邻接表表示图
int dist[100]; // 存储每个顶点到生成树中最近顶点的距离
bool visited[100]; // 标记顶点是否已被访问过
int minWeight = INF; // 最小生成树的权重和为无穷大,初始化为无穷大值
int minVertex = -1; // 最小生成树的最近顶点初始化为-1(未访问)
priority_queue, vector>, greater>> pq; // 小根堆实现最小堆结构
void prim() { // Prim算法实现最小生成树的核心函数
for (