01背包问题的三种解法

来源:互联网 发布:c语言所有函数 编辑:程序博客网 时间:2024/06/10 09:26

01背包问题是一种最简单的背包问题,也是很常见的一种问题,一下分别通过遍历法,贪心算法和动态规划算法来解决这一问题。

1、遍历法:将所有组合的情况遍历一遍,为了方便,将每种组合对应一个二进制数,例如:某个背包问题中有abcde五种物品,那么00001代表只放入了a,10001代表放入了a物品和e物品。则一共有2^5=32种情况,求出每种情况下的背包总价值,记录下背包总价值最大的情况,即为最后结果。

Java代码:

public static void Traversal_method(){//存放二进制数的数组,每一个二进制数代表一种组合情况,例如00001代表只放入了a物品String[] strs=new String[(int) Math.pow(2, list.size())];//得到所有二进制数for(int i=0;i<Math.pow(2, list.size());i++)strs[i]=tobinary(i);int maxvalue=0;int index=0;for(int count=0;count<strs.length;count++){String s=strs[count];//System.out.println("str="+s);//如果某一位为1,则将其对应的物品放入背包,如果超重换下一种,同事记录下这种情况背包的总价值for(int i=0;i<s.length();i++){if(s.charAt(i)=='1')if(!packet.putin(list.get(list.size()-i-1)))break;}//记录背包最大总价值,及其对应的数字if(packet.getValue()>maxvalue){maxvalue=packet.getValue();index=count;}//每种情况完成后,记得清理背包packet.clear();}System.out.println("背包总价值最大为:"+maxvalue);System.out.println("对应的二进制数:"+tobinary(index));}<span style="white-space:pre"></span>
<span style="white-space:pre"></span>public static String tobinary(int num)<span style="white-space:pre"></span>{        String str ="";        while(num !=0){        <span style="white-space:pre"></span>str =(num % 2) + str;            num =num/2;        }         while(str.length()<list.size())        <span style="white-space:pre"></span>str="0"+str;         return str;<span style="white-space:pre"></span>}
2、贪心算法:根据物品的value/weight即单位重量的价值,将所有物品排序又大到小排列,性价比高的拍到最前,然后按照顺序依次放入背包,知道背包再放不下下一个物品停止。

Java代码:

public static void Greedy_method(){//冒泡排序,根据value/weight的大小从大到小排列bubble_sort(list);//按照顺序放入背包,知道背包再放不下下一个物品for(int i=0;i<list.size();i++){if(!packet.putin(list.get(i)))break;}System.out.println("背包总价值最大为:"+packet.getValue());}
<span style="white-space:pre"></span>public static void bubble_sort(ArrayList<Item> list)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>for(int i=0;i<list.size();i++)<span style="white-space:pre"></span>for(int j=i;j<list.size();j++)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>if(list.get(i).getxingjiabi()<list.get(j).getxingjiabi())<span style="white-space:pre"></span>{<span style="white-space:pre"></span>Item temp=list.get(i);<span style="white-space:pre"></span>list.set(i, list.get(j));<span style="white-space:pre"></span>list.set(j, temp);<span style="white-space:pre"></span>}<span style="white-space:pre"></span>}<span style="white-space:pre"></span>}

3、动态规划算法:m为物品的序号,n为此时背包的最大承重,M为物品的总个数,N为背包的最大承重,w[m]=为第m个物品的重量,v[m]为第m个物品的价值,f[m][n]为有前m个物品,在放入最大承重为n的情况下的背包最大总价值。则算法描述如下:


f[m][n]矩阵


Java代码:

public static void DP_method(){int[][] packetmatrix=new int[list.size()+1][packet.getMAX_WEIGHT()+1];for(int i=0;i<list.size()+1;i++){for(int j=0;j<packet.getMAX_WEIGHT()+1;j++){//为矩阵第0行,第0列赋初始值0if(i==0 || j==0){packetmatrix[i][j]=0;//System.out.println("if  "+packetmatrix[i][j]);}else{//如果物品重量比背包总承重还要大,则矩阵此位置的值等于他上一行同列的值if(list.get(i-1).getWeight()>j){packetmatrix[i][j]=packetmatrix[i-1][j];}//否则,矩阵此位置的值等于max();else{packetmatrix[i][j]=Math.max(packetmatrix[i-1][j], packetmatrix[i-1][j-list.get(i-1).getWeight()]+list.get(i-1).getValue());}}}}//输出表格for(int i=0;i<list.size()+1;i++){for(int j=0;j<packet.getMAX_WEIGHT()+1;j++){System.out.print(packetmatrix[i][j]+"   ");}System.out.println();}//根据表格得到那些物品被选中int weight=packet.getMAX_WEIGHT();for(int i=list.size();i>=1;i--){//如果同一列,下面一行大于上面一行,说明该行对应的物品被选中if(packetmatrix[i][weight]>packetmatrix[i-1][weight]){packet.putin(list.get(i-1));weight-=list.get(i-1).getWeight();}if(weight==0)break;}System.out.println("maxvalue=="+packet.getValue());}

全局静态变量,以及main方法:
static MyPacket packet=new MyPacket();static ArrayList<Item> list=new ArrayList<Item>();public static void main(String[] args){Item a=new Item("a",2,1);Item b=new Item("b",3,4);Item c=new Item("c",6,6);Item d=new Item("d",5,4);Item e=new Item("e",4,6);list.add(a);list.add(b);list.add(c);list.add(d);list.add(e);//Traversal_method(); //遍历算法//Greedy_method();//贪心算法DP_method();//动态规划算法}
背包类:

public class MyPacket {private int weight;private int value;private final int MAX_WEIGHT=10;public boolean putin(Item item){if(this.weight+item.getWeight()<=MAX_WEIGHT){System.out.println("放入物品:"+item.getName());//items.add(item);this.weight+=item.getWeight();this.value+=item.getValue();return true;}else{System.out.println("背包已满");return false;}}public void clear(){this.weight=0;this.value=0;}public int getMAX_WEIGHT() {return MAX_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 class Item {private int weight;private int value;private String name;public Item(String name,int weight, int value) {this.weight = weight;this.value = value;this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}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 float getxingjiabi(){return (float)value/(float)weight;}}





0 0