算法java实现--动态规划--0-1背包问题

0-1背包问题算法的java实现(动态规划法)

具体问题描述以及C/C++实现参见网址

http://blog.csdn.net/liufeng_king/article/details/8683136

/**
 * 01 背包问题(动态规划)
 * @author Lican
 *
 */
public class Pack01 {
	public int[] v;//价值数组
	public int[] w;//重量数组
	public int c;//背包容量
	public int[][] m;//m(i,j)是背包容量为j,可选物品为,i,i+1,i+2,i+3,...,n 时0-1背包问题的最优值
	public int[] x;//保存第i个物品是否放入背包,1:放入;0:未放入
	public Pack01(int[] vv,int[] ww,int cc){
		this.v=vv;
		this.w=ww;
		this.c=cc;
		this.x=new int[vv.length];
		int max = maxM(w,c);//获取j的最大值,从而通过new关键字创建m数组,在内存中维数组分配相应的存储空间
		m = new int[v.length][max+1];
	}
	/**
	 * 获取重量和背包容量的最大值,从而为m创建相应的存储空间
	 * @param w
	 * @param c
	 * @return
	 */
	public int maxM(int[] w,int c){
		int max = c;
		for(int i=1;i<w.length;i++){
			if(w[i]>c)
				max=w[i];
		}
		return max;
	}
	public void knapsack(int[] v,int[] w,int c,int[][] m){
		int n =v.length-1;
		int jMax = Math.min(w[n]-1, c);
		for(int j = 0;j <= jMax;j++)
			m[n][j]=0;
		for(int j=w[n];j<=c;j++)
			m[n][j]=v[n];
		for(int i=n-1;i>1;i--){
			jMax=Math.min(w[i]-1,c);
			for(int j=0;j<=jMax;j++)
				m[i][j]=m[i+1][j];
			for(int j=w[i];j<=c;j++)
				m[i][j]=Math.max(m[i+1][j], m[i+1][j-w[i]]+v[i]);
		}
		//m[1][c]=m[2][c];
		if(c>=w[1])//对于i=1时的两种情况
			m[1][c]=Math.max(m[2][c], m[2][c-w[1]]+v[1]);
		else
			m[1][c]=m[2][c];
		
	}
	public void traceback(int[][] m,int[] w,int c,int[] x){
		int n=w.length-1;
		for(int i=1;i<n;i++){
			if(m[i][c]==m[i+1][c])//第i个包未放入
				x[i]=0;
			else{
				x[i]=1;
				c-=w[i];//c是全局变量
			}
		}
		x[n]=(m[n][c]>0)?1:0;
	}
	public static void main(String[] args) {
		int v[]={0,2,1,4,3};
		int w[]={0,1,4,2,3};
		int c=8;
		Pack01 pa = new Pack01(v,w,c);
		pa.knapsack(pa.v, pa.w, pa.c, pa.m);
		System.out.println("装入背包中物品总价值最大为:");
		System.out.println(pa.m[1][c]);
		pa.traceback(pa.m, pa.w, pa.c, pa.x);
		System.out.println("装入的物品的序号为:");
		for(int i=0;i<=v.length-1;i++){
			if(pa.x[i]==1)
				System.out.print(i+" ");
		}
	}
}

运行结果:



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值