博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
贪心算法——经典习题
阅读量:4074 次
发布时间:2019-05-25

本文共 8477 字,大约阅读时间需要 28 分钟。

¡贪心算法
§比较直观,容易想到
§对“图”要求高
§很多特殊图上的问题可以贪心,(参见《算法图论》)
§贪心问题的证明比较困难
§有时需要先排序,再贪心

¡  例1 找钱问题,目前的钱币系统1,2,5,10,用来换钱是最优的。

§  贪心的证明

▪      超过10 一定要用10,为什么?

▪      有5在,2的个数一定不超过3,因为如果有3个2,1个5,则换成1个10和1个1。

▪      没5在,2的个数不超过5。1,2凑超过10的,不如把10换掉。

▪      [5..9]一定要用5,为什么?枚举即可。

▪      [2..4]一定要用2,枚举即可。

§  注: {1,5,7}凑10就不可以贪心!

Java代码:
package com.zj;import java.util.Arrays;import java.util.HashMap;import java.util.Map;import java.util.Set;/* * 贪心算法解决超市找零问题( 所用纸币最少) *  * */public class KeepTheChange {	public static Map
GetChange(int[] money, int sum) { int len = money.length; if (0 == len) return null; Arrays.sort(money); Map map = new HashMap
(); int[] num = new int[len]; for (int i = len - 1; i >= 0; i--) { while (sum >= money[i]) { sum = sum - money[i]; num[i]++; } if (sum == 0) break; } for (int i = 0; i < len; i++) { map.put(money[i], num[i]); } return map; } public static void main(String[] arqs) { int[] money = new int[] { 1, 2, 5 }; Map map = GetChange(money, 28); Set
keys = map.keySet(); for (Integer i : keys) { System.out.println("value: " + i + " num: " + map.get(i)); } }}

¡  例2 活动安排 有若干个活动第i个开始时间和结束时间是[Si,fi),活动之间不能交叠,求最多安排多少个任务?

§  贪心原则: 按照结束时间排序,找所有不冲突的。

§  简证:有一个其他的最优解,我们把其中的活动也按照结束时间排序,我们可以把其中的任务一个一个换成我们贪心的任务,而不造成冲突。

Java代码:
package com.zj;import java.util.Arrays;import java.util.Collection;import java.util.Collections;import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;/* * 贪心算法:活动安排问题 * */public class ArrangeActivity {	public static Activity[] GetActivity(Activity[] activities) {		Arrays.sort(activities);		int len = activities.length;		int count = 0;		for (int i = 0; i < len; i++) {			for (int j = i + 1; j < len; j++) {				if (activities[j] != null && activities[i] != null						&& activities[j].start < activities[i].end) {					activities[j] = null;					count++;				}			}		}		Activity[] result = new Activity[len - count];		count = 0;		for (int i = 0; i < len; i++) {			if (activities[i] != null) {				result[count] = activities[i];				count++;			}		}		return result;	}	public static void main(String[] arqs) {		Activity[] test = new Activity[11];		test[0] = new Activity(1, 4);		test[1] = new Activity(3, 5);		test[2] = new Activity(0, 6);		test[3] = new Activity(5, 7);		test[4] = new Activity(3, 8);		test[5] = new Activity(5, 9);		test[6] = new Activity(6, 10);		test[7] = new Activity(8, 11);		test[8] = new Activity(8, 12);		test[9] = new Activity(2, 13);		test[10] = new Activity(12, 14);		Activity[] result = GetActivity(test);		System.out.println("there are " + result.length + "activities");		System.out.println("Details:");		for (int i = 0; i < result.length; i++) {			System.out.println(result[i].start + "  " + result[i].end);		}	}}/* * 实现Comparable接口 */class Activity implements Comparable
{ int start; int end; public Activity(int x, int y) { this.start = x; this.end = y; } @Override public int compareTo(Activity a1) { if (this.end < a1.end) return -1; if (this.end > a1.end) return 1; return 0; }}

¡  例3 最优装载 一艘船容量有限,想装载尽可能多的集装箱,每个集装箱的体积为xi,如何装载,使得装的集装箱个数尽可能多?

§  分析:贪心策略,按照最小的体积优先

§  简证: 也是通过“换”,把任意一个解所选的集装箱按体积排序,然后按顺序逐个换为我们贪心策略得到的解所选择的集装箱,占用的总体积不会增大……

Java代码:
package com.zj;import java.util.Arrays;/* * 贪心算法:最优装载 * */public class MaxLoad {	public static int[] maxLoad(int[] weight, int sum) {		int len = weight.length;		if (0 == len)			return null;		Arrays.sort(weight);		int count = 0;		for (int i = 0; i < len; i++) {			if (sum >= weight[i]) {				sum = sum - weight[i];				count++;			}			if (sum == 0)				break;		}		int[] result = new int[count];		for (int i = 0; i < count; i++)			result[i] = weight[i];		return result;	}	public static void main(String[] arqs) {		int[] weight = new int[] {1,1,2,3,14};		int[] result = maxLoad(weight, 12);		System.out.println("total load: "+result.length+" weights");		System.out.println("Details:");		for(int i=0;i

例4 部分背包 一个背包容量有限,若干个物体,每种物品有自己的体积和价值,每个物品可以拿一定比例,请让价值总和最大。

§  分析,按照每种物品“性价比”排。同样可以依靠交换,我们可以把任意解中选择的物品逐个换我们按贪心策略得到的解所选的物品,即换位同样体积的“更贵重”的物品,从而导致解更好。

Java代码:
package com.zj;import java.util.Arrays;/* * 贪心算法:部分背包问题 * */public class PartBag {	public static Article[] partbag(Article[] articles, int sum) {		int len = articles.length;		if (0 == len)			return null;		Arrays.sort(articles);		int count = 0;		int last_weight = Integer.MIN_VALUE;		for (int i = len - 1; i >= 0; i--) {			if (sum >= articles[i].weight) {				sum = sum - articles[i].weight;				count++;			} else if (sum != 0) {				last_weight = sum;				sum = 0;				count++;			}		}		Article[] result = new Article[count];		for (int i = 0; i < count; i++) {			if (i != count - 1) {				result[i] = articles[len - 1 - i];			} else {				if (last_weight == Integer.MIN_VALUE) {					result[i] = articles[len - 1 - i];				} else {					result[i] = new Article(last_weight,							articles[len - 1 - i].value									/ articles[len - 1 - i].weight									* last_weight);				}			}		}		return result;	}	public static void main(String[] arqs) {		Article[] test = new Article[3];		test[0] = new Article(2, 10);		test[1] = new Article(5, 12);		test[2] = new Article(5, 5);		Article[] result = partbag(test, 7);		System.out.println("there are " + result.length + " articles");		System.out.println("Details:");		for (int i = 0; i < result.length; i++) {			System.out.println("weight:" + result[i].weight + "   value:"					+ result[i].value);		}	}}class Article implements Comparable
{ int weight; long value; public Article(int x, long y) { this.weight = x; this.value = y; } @Override public int compareTo(Article a1) { long value_per_weight_1 = this.value; long value_per_weight_2 = a1.value; value_per_weight_1 = value_per_weight_1 / this.weight; value_per_weight_2 = value_per_weight_2 / a1.weight; if (value_per_weight_1 > value_per_weight_2) return 1; if (value_per_weight_1 < value_per_weight_2) return -1; return 0; }}package com.zj;import java.util.Arrays;/* * 贪心算法:部分背包问题 * */public class PartBag { public static Article[] partbag(Article[] articles, int sum) { int len = articles.length; if (0 == len) return null; Arrays.sort(articles); int count = 0; int last_weight = Integer.MIN_VALUE; for (int i = len - 1; i >= 0; i--) { if (sum >= articles[i].weight) { sum = sum - articles[i].weight; count++; } else if (sum != 0) { last_weight = sum; sum = 0; count++; } } Article[] result = new Article[count]; for (int i = 0; i < count; i++) { if (i != count - 1) { result[i] = articles[len - 1 - i]; } else { if (last_weight == Integer.MIN_VALUE) { result[i] = articles[len - 1 - i]; } else { result[i] = new Article(last_weight, articles[len - 1 - i].value / articles[len - 1 - i].weight * last_weight); } } } return result; } public static void main(String[] arqs) { Article[] test = new Article[3]; test[0] = new Article(2, 10); test[1] = new Article(5, 12); test[2] = new Article(5, 5); Article[] result = partbag(test, 7); System.out.println("there are " + result.length + " articles"); System.out.println("Details:"); for (int i = 0; i < result.length; i++) { System.out.println("weight:" + result[i].weight + " value:" + result[i].value); } }}class Article implements Comparable
{ int weight; long value; public Article(int x, long y) { this.weight = x; this.value = y; } @Override public int compareTo(Article a1) { long value_per_weight_1 = this.value; long value_per_weight_2 = a1.value; value_per_weight_1 = value_per_weight_1 / this.weight; value_per_weight_2 = value_per_weight_2 / a1.weight; if (value_per_weight_1 > value_per_weight_2) return 1; if (value_per_weight_1 < value_per_weight_2) return -1; return 0; }}

¡  例5 (独木舟) 有n个人,一条独木舟最多可以乘坐两个人且独木舟载重量有限(每条独木舟可载重量相同),每个人体重不一样,求这些人最少需要几条独木舟。

§  分析:最重的人肯定要上船,因此最重的人和另外一个人(船能承受的另外一个尽可能重的人)共乘一条独木舟,问题规模减少2。

Java代码:
package com.zj;import java.util.Arrays;/* * 贪心算法:独木舟问题 * */public class Canoe {	public static int maxPerson(int[] weight, int sum) {		int len = weight.length;		if (0 == len)			return 0;		Arrays.sort(weight);		int count = 0;		int index_1 = 0;		int index_2 = len - 1;		while (index_1 < index_2) {			if (weight[index_1] + weight[index_2] <= sum) {				index_1++;				index_2--;				count++;			} else {				count++;				index_2--;			}		}		if (index_1 == index_2)			count++;		return count;	}	public static void main(String[] arqs) {		int[] weight = new int[] { 5, 84, 85, 80, 84, 83 };		System.out.println(maxPerson(weight, 85));	}}

转载地址:http://npuni.baihongyu.com/

你可能感兴趣的文章
nginx+tomcat+memcached (msm)实现 session同步复制
查看>>
WAV文件解析
查看>>
WPF中PATH使用AI导出SVG的方法
查看>>
QT打开项目提示no valid settings file could be found
查看>>
android 代码实现圆角
查看>>
java LinkedList与ArrayList迭代器遍历和for遍历对比
查看>>
drat中构造方法
查看>>
JavaScript的一些基础-数据类型
查看>>
coursesa课程 Python 3 programming 统计文件有多少单词
查看>>
coursesa课程 Python 3 programming course_2_assessment_7 多参数函数练习题
查看>>
coursesa课程 Python 3 programming course_2_assessment_8 sorted练习题
查看>>
多线程使用随机函数需要注意的一点
查看>>
getpeername,getsockname
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>
No.182 - LeetCode1325 - C指针的魅力
查看>>
Encoding Schemes
查看>>
带WiringPi库的交叉笔译如何处理二之软链接概念
查看>>
Java8 HashMap集合解析
查看>>
自定义 select 下拉框 多选插件
查看>>