您的位置:首页 > 编程语言 > Java开发

(基于Java)算法之动态规划——0-1背包问题

2014-04-27 19:43 591 查看
动态规划的定义不解释,请读者移步到本博“最大K乘积问题”的博文中。

0-1背包问题描述:给定n种物品和一个背包。物品i的重量是wi,其价值为vi,背包的容量为c。问应如何选择装入背包中的物品,使得装入背包中的物品的总价值最大?

在本篇博文中,我将介绍如何用动态规划的方法来解决该问题。

首先,我们要找出原问题的最优子结构性质:

设x{x1,x2,x3......xn-1,xn}是最优解.


则x'{x2,x3,x4.......xn-1,xn}是子问题的最优解。

准备工作:

变量c用来表示背包的容量,变量n用来表示物品个数
一维数组w[],v[],分别用来存储物品i的重量和价值,为了方便第i个物品对应下标i,新建数组时可把数组长度设定为n+1
二维数组m[][],用来存储每个子问题的最优解,该二维数组的行列数最少都要n行c+1列(物品n个,重量c,算上0的话,一共c+1),为了方便第i个物品对应下标i,行数可以定义成n+1

解决方法:

解决办法是用自底向上的填表法

先看看这个问题的递归方程:



下面我贴出填表法的代码

public static int fun(int[] v, int[] w, int n, int c){
int[][] m = new int[n+1][c+1];
int i,j;
int jMax = getMin(w[n-1],c);
/*
* 这个for循环和下一个for循环的目的是利用vi进行初始化,
* 自己在张纸上手动填一下就知道为什么j的循环那么奇怪了。
*/
for(j = 0; j<=jMax; j++)
m
[j] = 0;
for(j = w
; j<=c; j++)
m
[j] = v
;
/*
* 在这个for循环中进行比较填入
*/
for(i = n-1; i>=1; i--){
jMax = getMin(w[i]-1,c);
for(j = 0; j<=jMax;j++)
m[i][j] = m[i+1][j];
for(j = w[i]; j<=c; j++)
m[i][j] = getMax(m[i+1][j],v[i]+m[i+1][j-w[i]]);
}
/*
* 因为填表方法是自底向上填表,因此,当i=1时,m[1][c]内
* 填入的数就是原问题的解,先将第一个子问题的最优解(即m[2][c])
* 填入,以防用0来做下一步的比较,后边的比较应该能看懂吧~不多说了
*/
m[1][c] = m[2][c];
if(c >= w[1])
m[1][c] = getMax(m[1][c],v[1]+m[2][c-w[1]]);
return m[1][c];
}

如有不对的地方或更好的建议,欢迎评论留言!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息