问题
一个可最大载重为X的背包和Y个物品,每个物品有重量和价值两个属性。现在让你用这个背包转物品,最多能装的价值是多少?
思路
1.定义变量
背包载重:X
物品数量:Y
每个物品的重量:wt[i] (y > i > 0 )
每个物品的价值:val[i] (y > i > 0 )
2.明确dp定义
dp[i][w]定义如下,对于前i个物品,当前背包容量为w时,可以装的最大价值是dp[i][w]。
比如dp[2][4] = 6,表示选择装前2个物品,背包容量是4时,最多可装的价值是6。
我们求的是dp[N][W]?
int dp[N+1][W+1]
dp[0][...] = 0 //前0个物品不论背包多少容量不会有价值
dp[...][0] = 0 //当前背包容量为0是不会再产生价值
//逻辑
for i in [1...N]:
for w in [1...W]:
dp[i][w] = max(把i物品装进包,不把i物品装进包)
return dp[N][W]
如果没有把第i件物品装入背包,那么dp[i][w] = dp[i-1][w]。
否则,dp[i][w] = dp[i-1][w - wt[i]] + val[i-1]。
for i in [1...N]:
for w in [1...W]:
dp[i][w] = max(dp[i-1][w - wt[i]] + val[i-1],dp[i-1][w])
return dp[N][W]
代码编写
public static void main(String[] args) {
//6件物品
int N = 6;
//背包容量为8
int W = 8;
//每个物品的重量
int[] wt = new int[]{2, 1, 3, 4, 5, 1};
//每个物品的价值
int[] val = new int[]{4, 2, 3, 4, 5, 1};
int knapsack = knapsack(W, N, wt, val);
System.out.println("最大能装的价值是" + knapsack);
}
public static int knapsack(int W, int N, int[] wt, int[] val) {
int[][] dp = new int[N + 1][W + 1];
for (int i = 1; i <= N; i++) {
for (int w = 1; w <= W; w++) {
if (w - wt[i - 1] < 0) {
//当前背包容量无法装下
dp[i][w] = dp[i - 1][w];
} else {
//当前物品可以装入,择优处理
dp[i][w] = Math.max(dp[i - 1][w - wt[i - 1]] + val[i - 1], dp[i - 1][w]);
}
}
}
return dp[N][W];
}