问题描述
小偷的背包容量是固定的W,物品重量wt[],对应的价值val[]。那么背包最大可以装多大的价值呢?
示例输入:
int[] val = {48,40,12,8,7};
int[] wt = {6,5,2,1,1};
int W =8;
最大价值目测是48+8+7=63,容量刚好为6+1+1=8.那么对于复杂的输入,该如何写算法呢?
动态规划思路
二维数组dp[][], 行表示物体重量wt,列从底至顶0,1,2...W.
决策:放不放第i个物体呢?不放,则为i-1时的价值;放,则为i-1个物体在剩余容量下的价值+当前物体价值
公式:
(1) v[i][0]=v[0][j]=0;
(2) v[i][j]=Math.max(v[i-1][j],v[i-1][j-wt[i]]+val[i]); //(wt[i]<=j)
(3) v[i][j]=v[i-1][j]; //(wt[i]>j)
step1:初始化
weight \ capacity | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
[0]->0 | –0– | –0– | –0– | –0– | –0– | –0– | –0– | –0– | –0– |
[1]->6 | –0– | ||||||||
[2]->5 | –0– | ||||||||
[3]->2 | –0– | ||||||||
[4]->1 | –0– | ||||||||
[5]->1 | –0– |
step1:从上到下从左到右依次填表
weight \ capacity | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
[0]->0 | –0– | –0– | –0– | –0– | –0– | –0– | –0– | –0– | –0– |
[1]->6 | –0– | > | |||||||
[2]->5 | –0– | ||||||||
[3]->2 | –0– | ||||||||
[4]->1 | –0– | V[raw][col] | |||||||
[5]->1 | –0– |
代码
public class BeiBao01 {
public static void main(String[] args) {
//先定义出背包的一些数属性
int[] val = {48,40,12,8,7};
int[] wt = {6,5,2,1,1};
int W =8;
//int[] val = {10,40,30,50};
//int[] wt = {5,4,6,3};
//int W =12;
int result = backpackage(val, wt, W);
System.out.println(result);
}
public static int backpackage(int[] val, int[] wt, int W){
//1.获得物品(或价值)总数目
int N = val.length;
//2.建一个矩阵,行和列都多一行。0行0列都填充0
/* w
* 0 1 2 3 4 5 6 7 8
*n 0
* 1 * * * * * * * *
* 2 *
* 3 *
* 4 *
* 5 *
*/
int[][] V = new int[N+1][W+1];
//3.将0行0列都值为零
for(int columns=0;columns<=W;columns++){
V[0][columns]=0;
}
for(int row=0;row<=N;row++){
V[row][0]=0;
}
//4.一行一行的填充,遍历二维数组即可
for(int row = 1;row<=N;row++){
for(int columns=1;columns<=W;columns++){
//5.算法的精髓:矩阵怎么填充呢?
// V[i][j]=V[i-1][j]或者是V[i-1][j-当前重量]+当前价值 中的较大的那个
if(wt[row-1]<=columns){ //单个重量比总容量小时。由于后边要做减法,做个判断(注意:等号不能忘)
V[row][columns]=Math.max(V[row-1][columns],
V[row-1][columns-wt[row-1]]+val[row-1]);
}else{
V[row][columns]=V[row-1][columns];
}
}
}
//6.选出最大值
//Printing the matrix
/*
for (int[] rows : V) {
for (int col : rows) {
System.out.format("%5d", col);
}
System.out.println();
}
*/
int i=N;
int j=W;
while(i>0&&j>0){
if(V[i][j]>V[i-1][j]){
System.out.println("第"+i+"件物品,重"+wt[i-1]+",价值"+val[i-1]+"放入");
j=j-wt[i-1];
i--;
}else{
i--;
}
}
return V[N][W];
}
}
//结果
第5件物品,重1,价值7放入
第4件物品,重1,价值8放入
第1件物品,重6,价值48放入
63