贪心算法-4.2背包问题

来源:互联网 发布:淘宝客推广位怎么设置 编辑:程序博客网 时间:2024/06/05 07:54

0-1背包问题

给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。

背包问题

0-1背包问题类似,所不同的是在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包,1≤i≤n。
这2类问题都具有最优子结构性质,极为相似,但背包问题可以用贪心算法求解,而0-1背包问题却不能用贪心算法求解。

用贪心算法解背包问题的基本步骤

首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。

用贪心算法解背包问题的算法步骤

①计算每个物品的单位价值v[i]/w[i]
②按每个元素的单位价值降序排序
③装载物品(分为完全装载和部分装载)

代码如下:

public class test4_2 {    public static float knapsack(float[] v,float[] w,float c,float[] x){        int n = v.length;        Element1[] d = new Element1[n];        //1.计算每个物品的单位价值v[i]/w[i]        for(int i=0;i<n;i++)            d[i] = new Element1(v[i]/w[i],w[i],v[i],i);        //2.按每个元素的单位价值降序排序        bobleSort(d);  //降序排序        //3.装载物品        int i;        float opt = 0;        for(i=0;i<n;i++) x[i] = 0;        ///3.1完全装载        for(i=0;i<n;i++){            if(d[i].w>c) break;  //第i个物品的重量大于背包剩余容量则跳出循环            x[i] = 1;            opt += d[i].v;            c -= d[i].w;        }        ///3.2部分装载        if(i<n){              x[i] = c/d[i].w;            opt += d[i].v*x[i];        }        return opt;    }    //冒泡降序排序    public static void bobleSort(Element1[] d){        int n = d.length;        Element1 temp;        for(int i=0;i<n-1;i++){            boolean ok = true;            for(int j=1;j<n-i;j++){                if(d[j-1].v_w<d[j].v_w){                    temp = d[j];                    d[j] = d[j-1];                    d[j-1] = temp;                    ok = false;                }            }            if(ok) break;        }    }    public static void main(String[] args) {        float[] w = {10,20,30};        float[] v = {60,100,120};        float c = 50;        float[] x = new float[v.length];        float v_max = knapsack(v,w,c,x);        System.out.println("装载物品价值最大为:"+v_max);    }}class Element1{    float v_w;    float w;    float v;    float index;    public Element1(float vw,float ww,float vv,float ii){        this.v_w = vw;        this.w = ww;        this.v = vv;        this.index = ii;    }}

运行结果如下:

装载物品价值最大为:240.0

总结
算法knapsack的主要计算时间在于将各种物品依其单位重量的价值从大到小排序。因此,算法的计算时间上界为O(nlogn)

动态规划和贪心算法的区别:
①动态规划法求解需要问题满足最优子结构性质,而贪心算法需要问题同时满足最优子结构性质贪心选择性质
动态规划法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行。
③通俗来讲:动态规划法原理可以类比语文中语句的断句,贪心算法原理可以类比给定某个容量往里面填充物品的例子。(这两个例子引用了女友和我讨论算法的对话)

原创粉丝点击