0-1背包问题测试代码

package ww;


public class test {

	void initial(int[] weight,int[] value,int n, int capacity)
	{
		int[][] maxvalue = new int[n][capacity+1];
		int[] trace = new int[n];
		maxvalue[0][0] = 0;
		for(int j=1;j<=capacity;j++)
		{
			if(weight[0]<=j)
				maxvalue[0][j] = value[0];
			else
				maxvalue[0][j] = 0;
		}
		ZeroOnePack(trace,maxvalue,weight,value,n-1,capacity);	
		print(weight,value,maxvalue,trace,n-1,capacity);
		
		System.out.println("最大重量为:"+maxvalue[n-1][capacity]);
		System.out.println("对应所选物品为:0表示没有选该物品,1表示选择了该物品");
		for(int k=0;k<=n-1;k++)
			System.out.println(trace[k]);
	}
	int ZeroOnePack(int[] trace,int[][] maxvalue,int[] weight,int[] value,int i,int j)
	{
		int x1=0,x2=0;
		if(i>=1 && j>=0)
		{
			x1=ZeroOnePack(trace,maxvalue,weight,value,i-1,j);
			x2=((j-weight[i])<0 ? 0:(ZeroOnePack(trace,maxvalue,weight,value,i-1,j-weight[i])+value[i]));
			if( x1 > x2 )
				return (maxvalue[i][j] = x1); 
			else
				return (maxvalue[i][j] = x2);
		}
		else if(i==0 && j>=0)	
				return maxvalue[0][j];	
		return 0;		
	}
	
	void print(int[] weight,int[] value,int[][] maxvalue,int[] trace,int i,int j)
	{//顺序输出,结果为0表示这个物品没有选择。
		if( i==0 && j>=0 && j-weight[i]>=0)
			trace[0]=1;
		else if( i>=1 && j>=0)
		{
			if(maxvalue[i-1][j] < maxvalue[i-1][j-weight[i]]+value[i])
				trace[i] =1;
			print(weight,value,maxvalue,trace,i-1,j-weight[i]);
		}
	}
	public static void main(String args[])
	{
		int[] value= {6,10,12};
		int[] weight={1,2,3};
		int n = value.length;
		test a = new test();
		a.initial(weight,value,n,5);
		System.out.println();
	}
}

物品编号从0开始。

这里的物品编号是从0开始的。单单实现求得最大值相对容易,但是要输出最后最大值是选择了哪些物品才得到的稍微会有点困难。无论物品编号是从0开始还是从1开始对这个问题而言都是一样的。0-1背包问题的求最大值的递归式为:


这里的m[i][j]中的i表示的第i个物品,j表示的可以容纳的最大的重量,上公式的max内的第一样表示不把第i个物品放入容量为j的包中,后一项表示要放入。在最后输出最大值对应的选择的物品时,采用的方式和求解最大值时的方法一样,也是递归的进行。整个问题是从上到下的递归的求解。

    0-1背包问题的动态规划解法和算法导论中的装配线调到问题有点类似,就一条装备线上而言,两者的相同点是对于一个点(装配点、物品)要么选择、要么不选择这样两种情况。也就是说最后的结果类似于000111101010011这样1断断续续出现的。这一点和矩阵乘法的动态规划的情况就不同,矩阵乘法的动态规划是连续的,也就是说不存在这样断开的情况,它的情况是知道所有的i等于j才停止。另外一个特点就是,他们都需要在递归式里,父问题总是对应着几种可能的子问题,然后从这几个子问题中找到一个最优的问题,而不是像矩阵乘法那样,通过对不同的切分点k来将问题分成两个子问题,然后找使得这个解最大的那个k作为父问题的最优解。从这两点来看,对于动态规划问题,我们可以先根据问题的解的情况大体给这个问题定一个位,这样可以会帮助我们分析找到递归式。

     另外,最后在最优解对应的物品时,即输出路径结果,我觉得有两种方法,一种是在求解最大值的时候做记录,然后再利用递归式输出路径结果;一种是不做记录,而是在递归输出时利用求解最大值过程中的目标值如这里的m[i][j]来帮助求解结果。当然我觉得对于这个背包问题,后一种方式处理可能会好点,还没有想到如何在计算中做记录,然后再利用递归输出路径结果。


你可能感兴趣的:(0-1背包问题测试代码)