经典0-1背包问题

0-1背包问题之动态规划策略解决

/**
 * 2."0-1"背包问题的动态规划算法
 */
package algorithm2;

public class Pack02 {
	/**
	 * v[]代表物体的价值,w[]代表物体的重量,c代表包的容量,<br>
	 * m[i][j]表示i~n个物品背包容量为j的最大价值<br>
	 * 
	 * @param v
	 * @param w
	 * @param c
	 * @param m
	 */
	public static void knapsack(int[] v, int[] w, int c, int[][] m) {
		int n = v.length - 1;
		//System.out.println(n);
		//System.out.println(w[n]);
		int jmax = Math.min(w[n] - 1, c);//jmax表示剩余重量且一个比w[n]小1的值,从1-jmax都无法装入包中
		//System.out.println(jmax);
		for (int j = 0; j < jmax; j++) {
			m[n][j] = 0; // 当w[n]>j有m[n][j]=0
			// System.out.println(m[n][0]+" "+m[n][1]+" "+m[n][2]+" "+m[n][3]);
		}
		// m[n][j]表示只有第n个物体时,背包的容量为j时最大价值
		for (int i = w[n]; i <= c; i++)
		{
			m[n][i] = v[n]; // 当w[n]<=j有m[n][j]=v[n]
			//System.out.print(m[n][i]+" ");
		}
		//System.out.println();
		// (先求出只装入最后一个物体价值--上面的两个for循环)至底向上递归调用求出m[][]其他值,直到求出m[0][c]
		for (int i = n - 1; i >= 1; i--) {
			jmax = Math.min(w[i] - 1, c);
			for (int k = 0; k <= jmax; k++)
				m[i][k] = m[i + 1][k]; //表示没有装入下一个物体的情况

			for (int h = w[i]; h <= c; h++) {    //从最后一个物体开始往前装物体
				m[i][h] = Math.max(m[i + 1][h], m[i + 1][h - w[i]] + v[i]);
				//System.out.print(m[i][h]+" ");
			}
		} 
		//System.out.println();
		m[0][c] = m[1][c];
		//System.out.println(m[1][c]);       
		if (c >= w[0])      //判断装没装第一个物体
			m[0][c] = Math.max(m[0][c], m[1][c - w[0]] + v[0]);
		System.out.println("bestw==" + m[0][c]);
	}

	public static void traceback(int[][] m, int[] w, int c, int[] x) {
		// 根据最优值求出最优解
		int n = w.length - 1;
		for (int i = 0; i < n; i++)
			if (m[i][c] == m[i + 1][c])
				x[i] = 0;
			else {
				x[i] = 1;
				c -= w[i];
			}
		x[n] = (m[n][c] > 0) ? 1 : 0;
	}

	public static void main(String[] args) {
		int[] wi = { 2, 4, 6, 5, 2 };
		int[] vi = { 6, 4, 3, 5, 2 };
		int[][] m = new int[11][11]; //11*11的二维数组保存结果
		knapsack(vi, wi, 10, m);
		int[] xi = new int[wi.length];
		traceback(m, wi, 10, xi);
		for (int i = 0; i < xi.length; i++)
			System.out.print(" " + xi[i]);
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值