当前位置:   article > 正文

初步理解:贪心算法_贪心算法的本质是什么

贪心算法的本质是什么

怎么理解贪心算法 

      贪心算法的本质就是找到每个阶段的局部最优,从而去推导全局最优。这么说可能有点抽象,举一个简单的例子:假设有一堆不同面额的钞票,从中取出十张,如何取才能得到最多的钱呢?这时候我们会有一个想法,只要每次取其中面额最大的钞票,依次取十次,那么所得的钞票总数就是最多的。在这个例子中,每次取出面额最大的钞票就是每个阶段里的局部最优,而所取到的钞票总数就是全局最优。从中我们可以看出,局部最优可以推出全局最优,这就是一个贪心策略

注意

贪心算法所得到的结果不一定是最优结果(有时候会是最优解),但是都是相对接近最优解的结果。

 因为贪心算法没有固定的解题方法,基本都是先找出每个阶段的局部最优方法,用局部最优方法来推导全局最优的解法,所以为了更好的理解贪心算法,我们来看几个例子以及其解决方法

一,今年暑假不AC

Problem Description

“今年暑假不AC?”

“是的“

”“那你干什么呢?”

“看世界杯呀,笨蛋!”

“@#$%^&*%...”

确实如此。世界杯来了,球迷的节日也来了,预计非常多ACMer也会抛开电脑。奔向电视了。

作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其他的节目。比方新闻联播(永远不要忘记关心国家大事)、很6+7、超级女生,以及王小丫的《开心辞典》等等。如果你已经知道了全部你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)

Input

输入数据包括多个測试实例。每一个測试实例的第一行仅仅有一个整数n(n\u003C=100)。表示你喜欢看的节目的总数。然后是n行数据,每行包括两个数据Ti_s,Ti_e (1\u003C=i\u003C=n),分别表示第i个节目的開始和结束时间,为了简化问题,每一个时间都用一个正整数表示。\nn=0表示输入结束,不做处理。

Output

对于每一个測试实例,输出能完整看到的电视节目的个数,每一个測试实例的输出占一行。Sample Input

12 1 3 3 4 0 7 3 8 15 19 15 20 10 15 8 18 6 12 5 10 4 14 2 9 0

Sample Output

5

 思路分析

我们要想知道最多可以观看多少节目,就要清楚每个节目的开始时间和结束时间,以及从中可以推出每个节目持续的时间长短。为了方便比较,我们先将各个时间段依照结束时间进行排序(按结束越早遍历。节目愈多再从第一个节目开始,假设下一节目开始时间大于上一节目的开始时间则进行该节目。依次递推。为了使代码的结构清晰方便理解。可以使用数组进行存储数据。

代码示例

  1. import java.util.*;
  2. public class jinnianshujiabuAC {
  3. public static void sort(int start[], int end[]) {//对开始时间和结束时间进行排序
  4. for (int i = 0; i < end.length - 1; i++) {
  5. for (int j = 0; j < end.length - 1 - i; j++) {
  6. if (end[j] > end[j + 1]) {
  7. int t1 = end[j];
  8. end[j] = end[j + 1];
  9. end[j + 1] = t1;
  10. int t2 = start[j];
  11. start[j] = start[j + 1];
  12. start[j + 1] = t2;
  13. }
  14. }
  15. }
  16. }
  17. public static void main(String[] args) {
  18. Scanner input = new Scanner(System.in);
  19. while (input.hasNext()) {
  20. int n = input.nextInt();
  21. if (n == 0) {
  22. break;
  23. }
  24. int[] start = new int[n];
  25. int[] end = new int[n];
  26. for (int i = 0; i < n; i++) {
  27. start[i] = input.nextInt();
  28. end[i] = input.nextInt();
  29. }
  30. sort(start, end);
  31. int count=1;
  32. int t=end[0];
  33. for (int i = 1; i < start.length; i++) {
  34. if(t<=start[i]){
  35. t=end[i];
  36. count++;
  37. }
  38. }
  39. System.out.println(count);
  40. }
  41. }
  42. }

二,胖老鼠的交易

Problem Description

胖老鼠准备M磅的猫粮,准备与守卫仓库的猫交易他最爱吃的JavaBean。仓库有N个房间。第i个房间包含J[I]的JavaBeans,需要F[I]磅的猫粮交换。每个房间可以按比例部分交换,你的任务是计算胖老鼠能获得的最多的JavaBeans。

Input

输入数据有多组,每组数据第一行包括两个正整数M、N,接下来有N行,每行有两个数J[I]和F[I],表示第i个房间JavaBean数量和需要的猫粮数量。当M和N都为-1输入结束。所有数字不会超过1000。

Output

对于每组输入数据,计算胖老鼠能获得的最大JavaBean数量并输出,结果保留三位小数,每个输出占一行。

样例输入

5 3

7 2

4 3

5 2

20 3

25 18

24 15

15 10

-1 -1

样例输出

13.333

31.500

思路分析

要想使胖老鼠得到的JAVABeans最多,那么就要使胖老鼠在每个房间收获的JAVABeans是最多的。我们可以先对房间按照单位猫粮所能收益的最大JAVABeans的值进行排序,从前往后进行遍历,如果猫粮有剩余就兑换。为了使代码写起来更加方便和更加准确,我们可以创建对象进行调用

 代码示例

  1. import java.util.Arrays;
  2. import java.util.Scanner;
  3. public class zhuixingzu {
  4. public static void main(String[] args) {
  5. Scanner input = new Scanner(System.in);
  6. while(input.hasNext()) {
  7. int n = input.nextInt();
  8. if(n == 0){
  9. break;
  10. }
  11. F[] perform = new F[n];
  12. for (int i = 0; i < n; i++) {
  13. perform[i] = new F();
  14. perform[i].setStar(input.nextInt());
  15. perform[i].setEnd(input.nextInt());
  16. }
  17. Arrays.sort(perform);
  18. int count = 1;
  19. int curEndTime = perform[0].getEnd();
  20. for (int i = 0; i < n; i++) {
  21. if (perform[i].getStar() >= curEndTime) {
  22. count++;
  23. curEndTime = perform[i].getEnd();
  24. }
  25. }
  26. System.out.println(count);
  27. }
  28. }
  29. }
  30. class F implements Comparable<F>{
  31. private int star;
  32. private int end;
  33. F(){}
  34. public F(int star, int end) {
  35. this.star = star;
  36. this.end = end;
  37. }
  38. public int getStar() {
  39. return star;
  40. }
  41. public int getEnd() {
  42. return end;
  43. }
  44. public void setStar(int star) {
  45. this.star = star;
  46. }
  47. public void setEnd(int end) {
  48. this.end = end;
  49. }
  50. @Override
  51. public int compareTo(F o) {
  52. return Integer.compare(this.end,o.end);
  53. }
  54. }

三,追星族

题目描述

小明最近迷上很多的女明星,恰逢她们正在巡回演出,得知所有的演出安排后,小明计划去看演出。但是有一些演出的时间重合,他在这个时间只能选择看其中一场演出,小明想尽可能多的看一些完整的演出,请你想想办法小明怎么安排能看更多完整的演出。

输入格式

输入数据有多组,每组数据的第一行有一个整数n(n≤100),表示演出的总数,然后是n行数据,每行包括两个数据si,ti (1≤i≤n),分别表示第i场演出的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。

输出格式

对于每组输入数据,输出小明最多能看完整演出的场数,每个输出占一行。

样例输入

11

3 5

1 4

5 7

0 6

5 9

3 8

6 10

8 11

2 13

8 12

12 14

0

样例输出

4

 思路分析

我们要想知道最多可以观看多少演出,就要清楚每场演出的开始时间和结束时间。这是一个区间调度问题,可以使用贪心算法来解决。首先将所有的演出按照开始时间进行排序,然后遍历排序后的演出列表,对于每一场演出,如果它的开始时间大于等于上一场演出的结束时间,那么就可以看这场演出,将计数器count加1。最后输出计数器的值。我们可以调用comparable接口来实现演出之间的比较

代码示例

  1. import java.util.Arrays;
  2. import java.util.Scanner;
  3. public class zhuixingzu {
  4. public static void main(String[] args) {
  5. Scanner input = new Scanner(System.in);
  6. while(input.hasNext()) {
  7. int n = input.nextInt();
  8. if(n == 0){
  9. break;
  10. }
  11. F[] perform = new F[n];
  12. for (int i = 0; i < n; i++) {
  13. perform[i] = new F();
  14. perform[i].setStar(input.nextInt());
  15. perform[i].setEnd(input.nextInt());
  16. }
  17. Arrays.sort(perform);
  18. int count = 1;
  19. int curEndTime = perform[0].getEnd();
  20. for (int i = 0; i < n; i++) {
  21. if (perform[i].getStar() >= curEndTime) {
  22. count++;
  23. curEndTime = perform[i].getEnd();
  24. }
  25. }
  26. System.out.println(count);
  27. }
  28. }
  29. }
  30. class F implements Comparable<F>{
  31. private int star;
  32. private int end;
  33. F(){}
  34. public F(int star, int end) {
  35. this.star = star;
  36. this.end = end;
  37. }
  38. public int getStar() {
  39. return star;
  40. }
  41. public int getEnd() {
  42. return end;
  43. }
  44. public void setStar(int star) {
  45. this.star = star;
  46. }
  47. public void setEnd(int end) {
  48. this.end = end;
  49. }
  50. @Override
  51. public int compareTo(F o) {
  52. return Integer.compare(this.end,o.end);
  53. }
  54. }

以上是我们作业中的几道贪心算法的练习题,我将其整理下来并做了简单总结,希望能帮助大家更好的理解贪心算法,也希望大家多多在评论区交流学习,一起学习编程知识。

新手小白报道,请大家多多指教!

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

闽ICP备14008679号