赞
踩
怎么理解贪心算法
贪心算法的本质就是找到每个阶段的局部最优,从而去推导全局最优。这么说可能有点抽象,举一个简单的例子:假设有一堆不同面额的钞票,从中取出十张,如何取才能得到最多的钱呢?这时候我们会有一个想法,只要每次取其中面额最大的钞票,依次取十次,那么所得的钞票总数就是最多的。在这个例子中,每次取出面额最大的钞票就是每个阶段里的局部最优,而所取到的钞票总数就是全局最优。从中我们可以看出,局部最优可以推出全局最优,这就是一个贪心策略。
注意
贪心算法所得到的结果不一定是最优结果(有时候会是最优解),但是都是相对接近最优解的结果。
因为贪心算法没有固定的解题方法,基本都是先找出每个阶段的局部最优方法,用局部最优方法来推导全局最优的解法,所以为了更好的理解贪心算法,我们来看几个例子以及其解决方法
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
我们要想知道最多可以观看多少节目,就要清楚每个节目的开始时间和结束时间,以及从中可以推出每个节目持续的时间长短。为了方便比较,我们先将各个时间段依照结束时间进行排序(按结束越早遍历。节目愈多再从第一个节目开始,假设下一节目开始时间大于上一节目的开始时间则进行该节目。依次递推。为了使代码的结构清晰方便理解。可以使用数组进行存储数据。
- import java.util.*;
- public class jinnianshujiabuAC {
- public static void sort(int start[], int end[]) {//对开始时间和结束时间进行排序
- for (int i = 0; i < end.length - 1; i++) {
- for (int j = 0; j < end.length - 1 - i; j++) {
- if (end[j] > end[j + 1]) {
- int t1 = end[j];
- end[j] = end[j + 1];
- end[j + 1] = t1;
-
- int t2 = start[j];
- start[j] = start[j + 1];
- start[j + 1] = t2;
- }
- }
- }
-
- }
-
- public static void main(String[] args) {
- Scanner input = new Scanner(System.in);
-
- while (input.hasNext()) {
- int n = input.nextInt();
- if (n == 0) {
- break;
- }
- int[] start = new int[n];
- int[] end = new int[n];
- for (int i = 0; i < n; i++) {
- start[i] = input.nextInt();
- end[i] = input.nextInt();
- }
- sort(start, end);
- int count=1;
- int t=end[0];
- for (int i = 1; i < start.length; i++) {
- if(t<=start[i]){
-
-
- t=end[i];
- count++;
- }
- }
- System.out.println(count);
- }
-
- }
-
- }
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的值进行排序,从前往后进行遍历,如果猫粮有剩余就兑换。为了使代码写起来更加方便和更加准确,我们可以创建对象进行调用
- import java.util.Arrays;
- import java.util.Scanner;
- public class zhuixingzu {
- public static void main(String[] args) {
- Scanner input = new Scanner(System.in);
- while(input.hasNext()) {
- int n = input.nextInt();
- if(n == 0){
- break;
- }
- F[] perform = new F[n];
- for (int i = 0; i < n; i++) {
- perform[i] = new F();
- perform[i].setStar(input.nextInt());
- perform[i].setEnd(input.nextInt());
- }
- Arrays.sort(perform);
- int count = 1;
- int curEndTime = perform[0].getEnd();
- for (int i = 0; i < n; i++) {
- if (perform[i].getStar() >= curEndTime) {
- count++;
- curEndTime = perform[i].getEnd();
- }
- }
- System.out.println(count);
- }
- }
- }
- class F implements Comparable<F>{
- private int star;
- private int end;
- F(){}
- public F(int star, int end) {
- this.star = star;
- this.end = end;
- }
-
- public int getStar() {
- return star;
- }
-
- public int getEnd() {
- return end;
- }
-
- public void setStar(int star) {
- this.star = star;
- }
-
- public void setEnd(int end) {
- this.end = end;
- }
-
- @Override
- public int compareTo(F o) {
- return Integer.compare(this.end,o.end);
- }
- }
题目描述
小明最近迷上很多的女明星,恰逢她们正在巡回演出,得知所有的演出安排后,小明计划去看演出。但是有一些演出的时间重合,他在这个时间只能选择看其中一场演出,小明想尽可能多的看一些完整的演出,请你想想办法小明怎么安排能看更多完整的演出。
输入格式
输入数据有多组,每组数据的第一行有一个整数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接口来实现演出之间的比较
- import java.util.Arrays;
- import java.util.Scanner;
- public class zhuixingzu {
- public static void main(String[] args) {
- Scanner input = new Scanner(System.in);
- while(input.hasNext()) {
- int n = input.nextInt();
- if(n == 0){
- break;
- }
- F[] perform = new F[n];
- for (int i = 0; i < n; i++) {
- perform[i] = new F();
- perform[i].setStar(input.nextInt());
- perform[i].setEnd(input.nextInt());
- }
- Arrays.sort(perform);
- int count = 1;
- int curEndTime = perform[0].getEnd();
- for (int i = 0; i < n; i++) {
- if (perform[i].getStar() >= curEndTime) {
- count++;
- curEndTime = perform[i].getEnd();
- }
- }
- System.out.println(count);
- }
- }
- }
- class F implements Comparable<F>{
- private int star;
- private int end;
- F(){}
- public F(int star, int end) {
- this.star = star;
- this.end = end;
- }
-
- public int getStar() {
- return star;
- }
-
- public int getEnd() {
- return end;
- }
-
- public void setStar(int star) {
- this.star = star;
- }
-
- public void setEnd(int end) {
- this.end = end;
- }
-
- @Override
- public int compareTo(F o) {
- return Integer.compare(this.end,o.end);
- }
- }
以上是我们作业中的几道贪心算法的练习题,我将其整理下来并做了简单总结,希望能帮助大家更好的理解贪心算法,也希望大家多多在评论区交流学习,一起学习编程知识。
新手小白报道,请大家多多指教!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。