当前位置:   article > 正文

数据结构和算法 二十一、贪心算法_数据结构与算法贪心算法

数据结构与算法贪心算法

1、贪心算法概述

        求解最优化问题的算法通常需要一系列的步骤,每个步骤面临很多选择。对于许多最优化问题,可以使用更简单、高效的算法。

        贪心算法(greedy algorithm)就是这样的算法,每一步都做出当时看起来最佳的选择。 贪心算法并不保证得到最优解。但是对于很多问题确实可以求得最优解。

为了达到最大和的目标,在每一步,贪心算法都会选择看起来是最优的直接选择,所以它会在第二步选择 12 而不是 3,并且不会达到包含 99 的最佳解决方案.

 

Dijkstra 算法,用于查找 ab之间的最短路径。它选择距离最短的未访问顶点,计算通过它到每个未访问邻居的距离,如果更小,则更新邻居的距离。与邻居完成后,标记已访问(设置为红色)。

2、活动选择问题

        考虑以下 6 个活动按完成时间排序。

        开始[] = {1, 3, 0, 5, 8, 5}; 完成[] = {2, 4, 6, 7, 9, 9};

        一个人最多可以进行四项活动。 这可以执行的最大活动集是 {0, 1, 3, 4} (这些是 start[] 中的索引和结束[] )

        贪心的选择是总是选择剩余活动中完成时间最短且开始时间大于或等于先前选择的活动的完成时间的下一个活动。我们可以根据完成时间对活动进行排序,以便我们始终将下一个活动视为最短完成时间的活动。

        1) 根据完成时间对活动进行排序。

        2) 从排序后的数组中选择第一个活动并打印。

        3) 对排序数组中的剩余活动执行以下操作。 

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. // 打印最多可以由一个人完成的活动,一次一个。
  4. // n --> 活动数量
  5. // s[] --> 包含所有活动开始时间的数组
  6. // f[] --> 包含所有活动完成时间的数组
  7. void printMaxActivities(int s[], int f[], int n)
  8. {
  9. int i, j;
  10. cout <<"Following activities are selected "<< endl;
  11. // The first activity always gets selected
  12. i = 0;
  13. cout <<" "<< i;
  14. // Consider rest of the activities
  15. for (j = 1; j < n; j++)
  16. {
  17. // 如果此活动的开始时间大于或等于之前选择的活动的结束时间,则选择它
  18. if (s[j] >= f[i])
  19. {
  20. cout <<" " << j;
  21. i = j;
  22. }
  23. }
  24. }
  25. int main()
  26. {
  27. int s[] = {1, 3, 0, 5, 8, 5};
  28. int f[] = {2, 4, 6, 7, 9, 9};
  29. int n = sizeof(s)/sizeof(s[0]);
  30. printMaxActivities(s, f, n);
  31. return 0;
  32. }

3、Kruskal最小生成树

        给定一个连通无向图,该图的生成树是一个子图,它是一棵树,将所有顶点连接在一起。一个图可以有许多不同的生成树。加权、连通、无向图的最小生成树 (MST)或最小权重生成树是权重小于或等于所有其他生成树的权重的生成树。

        算法步骤

        1、按权重的递增顺序对所有边进行排序。 

        2、选择最小的边。检查它是否与到目前为止形成的生成树形成一个循环。如果没有形成循环,则包括该边。否则,丢弃它。 

        3、重复步骤#2,直到生成树中有 (V-1) 条边。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. class DSU {
  4. int* parent;
  5. int* rank;
  6. public:
  7. DSU(int n)
  8. {
  9. parent = new int[n];
  10. rank = new int[n];
  11. for (int i = 0; i < n; i++) {
  12. parent[i] = -1;
  13. rank[i] = 1;
  14. }
  15. }
  16. // 查找方法
  17. int find(int i)
  18. {
  19. if (parent[i] == -1)
  20. return i;
  21. return parent[i] = find(parent[i]);
  22. }
  23. // union方法
  24. void unite(int x, int y)
  25. {
  26. int s1 = find(x);
  27. int s2 = find(y);
  28. if (s1 != s2) {
  29. if (rank[s1] < rank[s2]) {
  30. parent[s1] = s2;
  31. rank[s2] += rank[s1];
  32. }
  33. else {
  34. parent[s2] = s1;
  35. rank[s1] += rank[s2];
  36. }
  37. }
  38. }
  39. };
  40. class Graph {
  41. vector<vector<int> > edgelist;
  42. int V;
  43. public:
  44. Graph(int V) { this->V = V; }
  45. void addEdge(int x, int y, int w)
  46. {
  47. edgelist.push_back({ w, x, y });
  48. }
  49. void kruskals_mst()
  50. {
  51. // 1. 排序所有边
  52. sort(edgelist.begin(), edgelist.end());
  53. // 初始化
  54. DSU s(V);
  55. int ans = 0;
  56. cout << "Following are the edges in the "
  57. "constructed MST"
  58. << endl;
  59. for (auto edge : edgelist) {
  60. int w = edge[0];
  61. int x = edge[1];
  62. int y = edge[2];
  63. // 如果它确实形成一个循环,则在 MST 中占据优势
  64. if (s.find(x) != s.find(y)) {
  65. s.unite(x, y);
  66. ans += w;
  67. cout << x << " -- " << y << " == " << w
  68. << endl;
  69. }
  70. }
  71. cout << "Minimum Cost Spanning Tree: " << ans;
  72. }
  73. };
  74. int main()
  75. {
  76. /* 创建一个如下的图
  77. 10
  78. 0--------1
  79. | \ |
  80. 6| 5\ |15
  81. | \ |
  82. 2--------3
  83. 4 */
  84. Graph g(4);
  85. g.addEdge(0, 1, 10);
  86. g.addEdge(1, 3, 15);
  87. g.addEdge(2, 3, 4);
  88. g.addEdge(2, 0, 6);
  89. g.addEdge(0, 3, 5);
  90. g.kruskals_mst();
  91. return 0;
  92. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/251518?site
推荐阅读
相关标签
  

闽ICP备14008679号