动态规划之0--1分数背包问题

本文介绍了一种使用动态规划解决0-1背包问题的方法,通过具体实例展示了如何选择最大价值的物品组合放入有限承重的背包中,并提供了完整的Java实现代码。

1.问题

   已知现有物品m件(物品0,1,2,3,...m-1),背包的最大承重为n,计算把这个m件物品放到这个背包中可取得的最大价值。

   针对每个物品存有其名称、重量和价值。

/**
 * 表示每个物品的类。 
 */
class BagItem{
	String name;//物品的名字
	int weight;//物品的重量
	int value;//物品的价值
	
	public BagItem(String name,int weight,int value){
		this.name = name;
		this.weight = weight;
		this.value = value;
	}
}

2.采用动态规划的思想做这个题目

物理意义上用f[i][j]中存的是前i个物品放到最大承重为j的背包中可取得的最大重量。

决策方式:第i件物品是否放进去取决于放进去第i件物品得到的价值f[i-1][j-B[i].weight]+B[i].value(j>=B[i].weight) 和不放进去第i件物品时的价值f[i-1][j]比较结果.

s[i][j]表示在f[i][j]取得最大值时背包内的各个物品名称。

这样最后求的java数组中f[m-1][n]即为最大承重为n的背包中可放的那m件物品的最大重量。s[m-1][n]即为最后结果。

/**
 *  解决0-1背包问题
 *  动态规划.
 *  物理意义上f[i][j]中存的是前i个物品放到最大承重为j的背包中可取得的最大重量。
 *  第i件物品是否放进去取决于
 *  放进去第i件物品得到的价值f[i-1][j-B[i].weight]+B[i].value(j>=B[i].weight) 和不放进去第i件物品时的价值f[i-1][j]比较结果.
 *  s[i][j]表示在f[i][j]取得最大值时背包内的各个物品名称。
 *  
 */
public class Bag01 {
	public int[][] f;
	public String[][] s;
	int m;//物品总数
	int n;//背包的最大承重
	public Bag01(int m,int n){
		this.m = m;
		this.n = n;
		f = new int[m][n];
		s = new String[m][n];
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				s[i][j] = "";
				}
		}
	}
	
	public void selectBigValue(BagItem[] B){
		/*初始化代码第0件物品的操作操作*/
		for(int j=0;j<n;j++){
			if(j>=B[0].weight){
				f[0][j] = B[0].value;
				s[0][j] = B[0].name;
			}
		}
		/*按照决策公式决定下一件物品是否要放到背包中*/
		for(int i=1;i<m;i++){
			for(int j=0;j<n;j++){
				if(j>=B[i].weight && f[i-1][j-B[i].weight]+B[i].value > f[i-1][j] ){
					f[i][j] = f[i-1][j-B[i].weight] + B[i].value;
					s[i][j] = s[i-1][j-B[i].weight] + B[i].name;
				}else{
					f[i][j] = f[i-1][j];
					s[i][j] = s[i-1][j];
				}
			}
		}
		}
	}

在调用的时候需要注意:

如当背包的最大承重是10时,初始化矩阵为11行,j才可以取到10。

public static void main(String[] args){
		
		BagItem[] B = new BagItem[5];
		
		B[0] = new BagItem("f",2,6);
		B[1] = new BagItem("c",4,6);
		B[2] = new BagItem("d",5,4);
		B[3] = new BagItem("e",6,5);
		B[4] = new BagItem("b",2,3);
		/*注意:当背包的最大承重是10时,初始化矩阵为11行,j才可以取到10*/
		Bag01 test = new Bag01(5,10);
		test.selectBigValue(B);
		/*输出背包内的价值矩阵*/
		for(int i=0;i<test.m;i++){
			for(int j=0;j<test.n;j++){
				System.out.print(test.f[i][j]+"  ");
			}
			System.out.println();
		}
		/*输出对应f[i][j]取得最大值时背包内的物品名称。*/
		for(int i=0;i<test.m;i++){
			for(int j=0;j<test.n;j++){
				System.out.print(test.s[i][j]+"  ");
			}
			System.out.println();
		}
	}

代码的执行结果如下


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值