01背包问题的三种解法

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列赋初始值0
				if(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;
	}
	
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值