动态规划-03多重背包

紧接前面一篇,讲一下“多重背包”问题,该问题与“完全背包”相比,在每个物品的选取次数上给出了限定,即选取次数k不能无限的增大,其方程和“完全背包”的极度相似,只是k的限定条件发生了变化。

c[i][j] = max(c[i-1][j-(k*w[i-1])] + k*v[i-1], c[i-1][j]) (0 <= k <= counts[i])

其中,counts[i]表示第i件物品可选取的次数。

假设:定义可容纳总重量W =10 Kg,物品种类 N = 4,每件物品重量w[i],对应价值v[i],求解在可容纳重量范围内如何选取可获最大价值。

本题具体题目:


可能出现的情况:


以上表格同样是从左到右、从上到下生成,具体实现代码如下:

//一维数组实现多重背包问题,注意其中的二分法划分
	private static int[] BP_method03_1D(int m,int n,int[] w,int[] v,int[] counts){
		int c[] = new int[m+1];
		for (int i = 0; i < m+1; i++) {
			c[i] = 0;//不必完全装满,则全部初始化为0
		}
		for (int i = 0; i < n; i++) {
			//过滤掉次数小于2的物品
			for(int k = 1; k < counts[i]; k <<= 1){
					for (int j = m; j >= k * w[i]; j--) {//限定总重量
						c[j] = Math.max(c[j-k*w[i]] + k*v[i], c[j]); 
					}
				counts[i] -= k;
			}
			//此处为次数为1的物品
			for (int j = m; j >= w[i]; j--) {//限定总重量
					c[j] = Math.max(c[j-w[i]] + v[i], c[j]); 
			}
		}
		return c;
	}
//二维数组实现,此处代码和前一篇“完全背包”二维数组方法中的源码基本一样,仅是k的取值由‘k*w[i-1] <= m’变为‘k <= counts[i]’
	private static int[][] BP_method03_2D(int m,int n,int[] w,int[] v,int[] counts){
		int c[][] = new int[n+1][m+1];
		List<Integer> list = new ArrayList<>(); 
		for (int i = 0; i < n+1; i++) {
			c[i][0] = 0;
		}
		for (int i = 0; i < m+1; i++) {
			c[0][i] = 0;
		}
		for (int i = 1; i <= n; i++) {//限定物品种类,无重复
			for (int j = 1; j <= m; j++) {//限定总重量
				list.clear();
				for (int k = 0; (k <= counts[i-1]) && (k >= 0); k++) {
					if (j >= k*w[i-1]) {
						list.add( Math.max(c[i-1][j-(k*w[i-1])] + k*v[i-1], c[i-1][j]));
					}
				}
				c[i][j] = Collections.max(list);
			}
		}
		return c;
	}

其输出结果如下:

一维选取:
0 0 5 5 10 10 13 14 16 17 17  
二维选取:
0  3  3  6  6  6  6  6  6  6  
0  3  4  6  7  7  10  10  10  10  
0  5  5  10  10  13  14  16  17  17  
0  5  5  10  10  13  14  16  17  17




猜你喜欢

转载自blog.csdn.net/xiaoxun2802/article/details/80018649
今日推荐