【算法系列-10】贪心算法

声明:内容源自网络

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


贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。


基本思路

贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,他的选取应该满足局部优化的条件。若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加算法停止。

过程
①建立数学模型来描述问题;
②把求解的问题分成若干个子问题;
③对每一子问题求解,得到子问题的局部最优解;
④把子问题的解局部最优解合成原来解问题的一个解。


0-1背包问题

有一个背包,背包容量是M=150kg。有7个物品,物品不可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
物品 A B C D E F G
重量 35kg 30kg 6kg 50kg 40kg 10kg 25kg
价值 10$ 40$ 30$ 50$ 35$ 40$ 30$

分析:
目标函数:∑pi最大
约束条件是装入的物品总重量不超过背包容量:∑wi<=M(M=150)
⑴根据贪心的策略,每次挑选价值最大的物品装入背包,得到的结果是否最优?
⑵每次挑选所占重量最小的物品装入是否能得到最优解?
⑶每次选取单位重量价值最大的物品,成为解本题的策略。

代码

物品类:

public class Goods implements Comparable<Goods> {
	private int weight;
	private int value;
	/*单位重量价值*/
	private int unitValue;
	
	public Goods(int weight, int value){
		this.weight = weight;
		this.value = value;
		this.unitValue = (weight == 0) ? 0 : (value/weight);
	}

	public int getWeight() {
		return weight;
	}

	public void setWeight(int weight) {
		this.weight = weight;
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	public int getUnitValue() {
		return unitValue;
	}

	public void setUnitValue(int unitValue) {
		this.unitValue = unitValue;
	}

	@Override
	public int compareTo(Goods o) {
		// TODO Auto-generated method stub
		int value = o.unitValue;
		if(unitValue > value)
			return 1;
		if(unitValue < value)
			return -1;
		
		return 0;
	}

}

背包类:

public class Knapsack {
	private List<Goods> list;
	/*背包总承重*/
	private int bWeight;
	/*背包价值*/
	private int totalValue;
	
	public Knapsack(int bWeight){
		this.bWeight = bWeight;
		this.list = new ArrayList<Goods>();
	}
	
	public List<Goods> getList() {
		return list;
	}
	public void setList(List<Goods> list) {
		this.list = list;
	}
	public int getbWeight() {
		return bWeight;
	}
	public void setbWeight(int bWeight) {
		this.bWeight = bWeight;
	}

	public int getTotalValue() {
		totalValue = 0;
		
		for(Goods goods : list){
			totalValue += goods.getValue();
		}
		
		return totalValue;
	}
	
	
}

算法类

/**
 * Program Name:
* Description:贪心算法
* Methods:
* @version ver:1.0

*/
public class GreedyAlg {
	private Knapsack knapsack;
	private Goods[] goodsArray;
	
	public GreedyAlg(Knapsack knapsack, Goods[] goodsArray){
		this.knapsack = knapsack;
		this.goodsArray = goodsArray;
		/*对货物按照单位重量价值从大到小排序*/
		Arrays.sort(goodsArray, Collections.reverseOrder());
	}
	
	public void solve(){
		int currentWeight = 0;

		List<Goods> list = knapsack.getList();
		for(int i=0; i<goodsArray.length; i++){
			/*判断当前货物是否可以放到包中,如不能则继续循环*/
			if(currentWeight + goodsArray[i].getWeight() > knapsack.getbWeight())
				continue;
			currentWeight += goodsArray[i].getWeight();
			list.add(goodsArray[i]);

		}
	}
	
	public static void main(String[] args){
		Knapsack knapsack = new Knapsack(150);
		
		Goods goodsA = new Goods(35, 10);
		Goods goodsB = new Goods(30, 40);
		Goods goodsC = new Goods(6, 30);
		Goods goodsD = new Goods(50, 50);
		Goods goodsE = new Goods(40, 35);
		Goods goodsF = new Goods(10, 40);
		Goods goodsG = new Goods(25, 30);
		
		Goods[] array = {goodsA, goodsB, goodsC, goodsD, goodsE, goodsF, goodsG};
		
		GreedyAlg greedyAlg = new GreedyAlg(knapsack, array);
		greedyAlg.solve();
		
		int totalValue = knapsack.getTotalValue();
		System.out.println("Input Knapspack total value is----->" + totalValue);
		
	}
}

总结

贪心算法不回溯,只是局部最优解,请注意!

贪心算法不保证能得到最优解,动态规划可以得到最优解。

动态规划每次都要回朔处理,这样的话效率不高。如果只为求最优解,动态规划自然更好!但是如果对效率有要求,对最优解的值没有严格要求,贪心法就适用了。根据实际问题的取舍很重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值