背包问题的自己理解

0-1背包和完全背包问题的实现

	public static void print(int[][] a) {<span style="white-space:pre">				</span>
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[0].length; j++) {
				System.out.print(a[i][j] + "\t");
			}
			System.out.println();
		}
	}
	//完全的背包问题
	public static void comlete(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++) {			//这点与0-1背包问题不同,根据当前背包的容量判断可以装入几个当前物品
			m[n][j] = v[n] * (j / w[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++) {
				int f = j / w[i];	
				//这点跟0-1背包问题不同,但是原理一样,判断在当前背包容量的情况下装入多个当前物品,所以剩余容量以及价值都要乘以当前课以装<span style="white-space:pre">				</span>入数
				m[i][j] = Math.max(m[i + 1][j], m[i + 1][j - w[i] * f] + v[i] * f);	
			}
		}
		print(m);
		int[] x = new int[6];
		tracebake1(m, w, v, c, x);
	}

	public static void knasp(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 + 1][j - w[i]] + v[i]是背包如果装入当前物品的价值,j - w[i]为背包剩余的容量,根据剩余判断前一个物品在这个剩余容量时的价值即m[i + 1][j - w[i]]
				//m[i + 1][j]表示前一个物品在当前容量为j的情况是的价值
				m[i][j] = Math.max(m[i + 1][j], m[i + 1][j - w[i]] + v[i]);
			}
		}
		print(m);
		int[] x = new int[6];
		tracebake(m, w, c, x);
	}

	private static void tracebake1(int[][] m, int[] w,int[] v, int c, int[] x) {
		int n = w.length - 1;
		for (int i = 1; i < n; i++) {
			if (m[i][c] == m[i + 1][c]) {		//当前位置与前一行当前位置的值相同代表没装入
				x[i] = 0;
			} else {
				x[i] = m[i][c]/v[i];
				c -= w[i]*m[i][c]/v[i];
			}
		}
		x[n] = (m[n][c] > 0) ? 1 : 0;
		for (int a : x) {
			System.out.print(a + ",");
		}
		System.out.println();
	}
	/**
	 * 回溯求解对于各个物品是否装入
	 * @param m
	 * @param w
	 * @param c
	 * @param x
	 */
	 
	private static void tracebake(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]) {
				x[i] = 0;
			} else {
				x[i] = 1;
				c -= w[i];
			}
		}
		x[n] = (m[n][c] > 0) ? 1 : 0;
		for (int a : x) {
			System.out.print(a + ",");
		}
	}

	public static void main(String[] args) {
		int[] v = new int[] { 0, 6, 3, 5, 4, 6 }; 		//物品的价值  创建6个只是为了统一下标
		int[] w = new int[] { 0, 2, 2, 6, 5, 4 };		//物品的重量
		int[][] m = new int[6][11];				//2维数组记录背包的价值状态
		int c = 10;						//背包容量
		knasp(v, w, c, m);
//		comlete(v, w, c, m);
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值