参考:视频:http://new-play.tudou.com/v/448118973.html?spm=a2hzp.8253869.0.0
看了网上强推的背包九讲,但没看太明白,看了视频再相结合,对背包问题有了自己的理解。
1.背景描述
有N件物品,每件物品的重量未w1,w2……wN,每件物品有相应的价值为v1,v2……vN;现在有一个容量为C的背包,现在要将物品放到背包中,使得背包中所含物品的价值最高。
2.公式表示
用一个二维数组来表示背包中的价值f[i][v],i表示前i个物品,v表示背包中剩余容量。
对于第i件物品,(1) 物品的重量过大,无法放入背包 f[i][v]=f[i-1][v]
(2) 物品可以放入背包,但要选择是否放入(取最大值)
i,放 f[i][v]=f[i-1][v-wi]+v(i)
ii,不放 f[i][v]=f[i-1][v]
在这里,可以考虑用递归的方法来做,但是递归的方法无法记录上一个状态的情况,所以要用动态规划的思路来做。
3.推导过程
以下图为例 此图来源于:http://karaffeltut.com/NEWKaraffeltutCom/Knapsack/knapsack.html(有兴趣可以来做实验)
第一行表示背包容量依次为1.2.3.4.5……18的时候,不放商品的时候的价值,也就是为0;
第二行表示,只允许放商品一的时候的背包价值
第三行表示,只允许放商品一和商品二的时候的背包价值
同理,最后一行表示这些商品都允许放入的时候的背包价值。
4.代码实现
package Algorithm;
public class kanpsack {
private static int N = 8;
private static int W = 18;
private static int B[][] = new int[N][W];
private static void kanp(){
int w[] = {0,4,6,5,7,3,1,6};
int v[] = {0,12,10,8,11,14,7,9};
for (int k = 1;k< N;k++){
for (int c = 1; c <W; c++)
if (w[k] >c){
B[k][c] = B[k-1][c];
}else{
int value1 = B[k-1][c-w[k]] + v[k];
int value2 = B[k-1][c];
if (value1 > value2){
B[k][c] = value1;
}else {
B[k][c] = value2;
}
}
}
}
public static void main(String[] args) {
kanp();
System.out.println(B[7][17]);
}
}