433-贪心算法编程实战

向右看齐 2022-09-05 06:10 291阅读 0赞

贪心算法思想

在这里插入图片描述
贪心算法:符合每一步的最优解,但是不一定是原问题的最优解

硬币问题

1,3,5分的硬币,现在给定一个价值c:11,问组成价值c需要的最少的硬币的数量???
贪心算法,就是一直优先选大的面值的硬币。
刚开始一直选5分硬币,选不了5分的硬币了,就选3分的,3分的硬币也选不了了,就选1分的硬币。

  1. #include <iostream>
  2. #include <algorithm>//泛型算法的头文件
  3. using namespace std;
  4. int main()
  5. {
  6. int arr[] = {
  7. 1,3,5 };
  8. int length = sizeof(arr) / sizeof(arr[0]);
  9. int c = 11;
  10. sort(arr, arr + length, [](int a, int b)->bool {
  11. return a > b; });//降序排序
  12. int idx = 0;// 5 3 1
  13. int cnt = 0;//记录硬币的个数
  14. while (c > 0)
  15. {
  16. if (c >= arr[idx])
  17. {
  18. c -= arr[idx];
  19. cnt++;//硬币数加1
  20. }
  21. else
  22. {
  23. idx++;//数组下标往后走
  24. }
  25. }
  26. cout << cnt << endl;
  27. return 0;
  28. }

运行截图如下
在这里插入图片描述

部分背包问题

部分背包问题
有n个物体,第i个物体的重量为wi,价值为vi。在总重量不超过C的情况下让总价值尽量高。
也就是说,每一个物体都可以只取走一部分,价值和重量按比例计算。求最大总价值。
也就是说,贪心算法可以一定要把c占满,优先把价值高的往里放。

贪心算法 -解决01背包 - 不一定得到最优解,因为在0-1背包,物品只存在放与不放,不能只放一个物品的其中的一部分,所以最后不一定把背包的容量占满

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. //描述物品的类
  5. struct Product
  6. {
  7. double getPrice()const//获取性价比
  8. {
  9. return v * 1.0 / w;
  10. }
  11. bool operator>(const Product& p) const//重载大于>
  12. {
  13. return getPrice() > p.getPrice();
  14. }
  15. int id;//物品的id
  16. int w;//物品的重量
  17. int v;//物品的价值
  18. };
  19. int main()
  20. {
  21. int w[] = {
  22. 8,6,4,2,5 };
  23. int v[] = {
  24. 6,4,7,8,6 };
  25. const int n = sizeof(w) / sizeof(w[0]);//物品的个数
  26. int c = 12;
  27. int x[n] = {
  28. 0 };//初始都给个0,有使用的置为1
  29. Product pros[n];
  30. for (int i = 0; i < n; ++i)//初始化
  31. {
  32. pros[i].id = i;
  33. pros[i].w = w[i];
  34. pros[i].v = v[i];
  35. }
  36. //按物品的性价比降序排列
  37. sort(pros, pros + n, [](const Product& p1, const Product& p2)->bool {
  38. return p1 > p2; });
  39. //按性价比高的往背包里面放(只考虑局部的最优解)
  40. double bestv = 0.0;//记录背包的最大价值
  41. for (int i = 0; i < n; ++i)
  42. {
  43. if (pros[i].w <= c)
  44. {
  45. //说明第i个物品可以装入背包
  46. bestv += pros[i].v;
  47. c -= pros[i].w;
  48. }
  49. else
  50. {
  51. //说明第i个物品无法全部装入背包,按剩余容量的比例装入物品的一部分
  52. bestv = bestv + pros[i].v * (c * 1.0 / pros[i].w);
  53. x[pros[i].id] = 1;
  54. break;//说明已经装完了!!!
  55. }
  56. x[pros[i].id] = 1;
  57. }
  58. cout << "bestv:" << bestv << endl;
  59. for (int v : x)
  60. {
  61. cout << v << " ";
  62. }
  63. cout << endl;
  64. return 0;
  65. }

运行截图如下
在这里插入图片描述

柜台提供服务问题

m个柜台提供服务,每个柜台给一个用户提供服务的时间是t(用数组表示每一个柜台提供服务的时间),
问怎么排列,使得柜台给所有用户提供服务的时间最少?

贪心算法就是优先给给用户提供服务的时间的最少的柜台分配用户,然后再试着给其他的花费比较少时间的柜台分配用户

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. //定义柜台类
  5. struct Counter
  6. {
  7. //描述柜台
  8. bool operator<(const Counter &counter) const//重载<
  9. {
  10. return time < counter.time;
  11. }
  12. int id;//柜台id
  13. int time;//柜台提供服务所花费的时间
  14. };
  15. int main()
  16. {
  17. int arr[] = {
  18. 3,2,4 };//每一个柜台处理每个用户所服务的时间
  19. const int m = sizeof(arr) / sizeof(arr[0]);//柜台的数量 3
  20. int n = 15;//办理业务的用户人数
  21. //定义柜台信息数组,初始化柜台id和time
  22. Counter cons[m];
  23. for (int i = 0; i < m; ++i)
  24. {
  25. cons[i].id = i;
  26. cons[i].time = arr[i];
  27. }
  28. //按照柜台提供服务的时间升序排列
  29. sort(cons, cons + m);//从小到大排序
  30. int mintime = 0;//记录给所有用户提供服务的最少时间
  31. int x[m] = {
  32. 0 };//记录每一个柜台安排的用户数量
  33. for (int i = 0; i < n; ++i)//遍历所有的用户
  34. {
  35. //先计算把i用户放在0号柜台的时间,因为0号柜台提供服务的时间最快
  36. int time = cons[0].time * (x[0] + 1);//0号柜台的i用户之前的人在x[0]放着,不着急给x[0]++,我们只是假设先放在0号柜台
  37. //因为不一定放在0柜台,有可能0号柜台人很多了,放在其他柜台效率还高呢
  38. //再遍历其它的柜台,看是否可以得到更少的花费时间
  39. int j = 1;
  40. for (; j < m; ++j)
  41. {
  42. int t = cons[j].time * (x[j] + 1);
  43. if (t <= time)
  44. {
  45. //放在其它柜台处理时间总体更快,直接放入j柜台
  46. x[j]++;
  47. //新添加了一个人,整体花费的时间有可能变得更长了,更新mintime
  48. if (t > mintime)
  49. {
  50. mintime = t;
  51. }
  52. break;
  53. }
  54. }
  55. //最终还是放在0号柜台花费时间最少
  56. if (j == m)
  57. {
  58. x[0]++;
  59. //新添加了一个人,整体花费的时间有可能变得更长了,更新mintime
  60. mintime = cons[0].time * x[0];
  61. }
  62. }
  63. cout << mintime << endl;
  64. for (int i = 0; i < m; ++i)
  65. {
  66. cout << arr[cons[i].id] << " : " << x[i] << endl;
  67. }
  68. return 0;
  69. }

运行截图如下
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,291人围观)

还没有评论,来说两句吧...

相关阅读

    相关 贪心算法实战

    贪心算法实战 > 贪心算法就是按照我们人类最想要的想法去完成某件事情(每次都尝试找到局部最优解) > 贪心算法只适用于某些特定的算法题,并且不好证明【用对数器验证】

    相关 贪心算法

    贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,所做出的是在某种意义上的局部最优解。举一个简单的贪心法例子,平时

    相关 贪心算法

    1.钞票支付问题,1元,2元,5元,10元,20元,50元,100元钞票无穷张,使用这些钞票怎么支付,最少需要多少张。 思路:尽可能使用面额较大的金额数目。反证法:若不成立,

    相关 贪心算法

    一、什么是贪心算法 贪心算法,又称贪婪算法(Greedy Algorithm),是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优解出发来考虑,它