概述
- 贪心算法(
Greedy Algorithm
)是一种构造性算法,用于解决最优化问题 - 其核心思想是在每一步选择中,都采取当前状态下最优的选择,期望通过一系列局部最优的选择达到全局最优
- 贪心算法在许多实际问题中非常有效,但并不是所有问题都适用
特点
- 局部最优选择
- 每一步都选择当前状态下的最佳解决方案,不考虑未来可能的后果
- 全局最优性
- 在某些问题中,局部最优选择能够确保全局最优解决方案,但并不是所有问题都满足这一条件
- 无需回溯
- 一旦做出选择,不需要回退或修改之前的选择
适用场景
- 贪心选择性质:
- 问题在每一步选择时,局部最优选择不会影响全局最优解的正确性
- 最优子结构性质:
- 问题能够分解为子问题,并且子问题的最优解可以递归地构建成全局最优解
优缺点
优点
- 简单易行:
- 贪心算法通常比较简单,容易实现
- 高效:
- 大多数情况下,贪心算法的时间复杂度较低,能够在较短时间内得到结果
缺点
- 局限性:
- 贪心算法并不总是能保证得到全局最优解,尤其是当问题不满足贪心选择性质和最优子结构性质时
- 适用性有限:
- 只有部分优化问题适合使用贪心算法
应用实例
- 活动选择问题
- 选择最多的活动在不重叠的情况下
- 背包问题
- 选择物品放入背包,以达到最大价值(适用于分数背包问题)
- 哈弗曼编码
- 最优编码树的构建,用于数据压缩
- 最小生成树问题
Kruskal
和Prim
算法
- 单源最短路径问题
- 狄克斯特拉
Dijkstra
算法(适用于非负权重的图)
- 狄克斯特拉
算法示例
活动选择问题
- 给定一组活动,每个活动有一个开始时间和结束时间,选择尽可能多的活动使它们不重叠
- 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#include <iostream> #include <vector> #include <algorithm> using namespace std; struct Activity { int start; int end; }; bool compare(Activity a1, Activity a2) { return a1.end < a2.end; } void activitySelection(vector<Activity>& activities) { sort(activities.begin(), activities.end(), compare); cout << "Selected activities: " << endl; int last_end = -1; for (auto& activity : activities) { if (activity.start >= last_end) { cout << "Activity(" << activity.start << ", " << activity.end << ")" << endl; last_end = activity.end; } } } int main() { vector<Activity> activities = {{1, 3}, {2, 5}, {4, 7}, {1, 8}, {5, 9}, {8, 10}}; activitySelection(activities); return 0; } |
return a1.end < a2.end;
- 这个比较的效果,就是把所有活动按活动结束时间进行排序
- 选择最早结束的活动一方面可以给剩下的活动留出更多可选的时间
- 一方面可以最大限度地避免活动之间的重叠冲突
背包问题
- 给定一组物品,每个物品有一个重量和价值,选择放入背包中的物品使得总价值最大化,允许分割物品
- 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#include <iostream> #include <vector> #include <algorithm> using namespace std; struct Item { int weight; int value; }; bool compare(Item a, Item b) { double r1 = (double)a.value / a.weight; double r2 = (double)b.value / b.weight; return r1 > r2; } double fractionalKnapsack(int W, vector<Item>& items) { sort(items.begin(), items.end(), compare); int currentWeight = 0; double finalValue = 0.0; for (auto& item : items) { if (currentWeight + item.weight <= W) { currentWeight += item.weight; finalValue += item.value; } else { int remain = W - currentWeight; finalValue += item.value * ((double)remain / item.weight); break; } } return finalValue; } int main() { int W = 50; // 背包容量 vector<Item> items = {{10, 60}, {20, 100}, {30, 120}}; double maxValue = fractionalKnapsack(W, items); cout << "Maximum value in Knapsack = " << maxValue << endl; return 0; } |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 匹配_Rabin_karp匹配算法10/15
- ♥ 动态规划_最长公共子序列09/05
- ♥ 匹配_KMP模式匹配算法:一11/02
- ♥ 排序_计数排序05/08
- ♥ 数据结构模板03/09
- ♥ 匹配_KMP模式匹配算法:二10/09