一、01背包问题
(1)题目:
01背包问题:(因为对每个物品只有选和不选两种情况,所以这个问题称为01背包)
有n个重量和价值分别为wi, vi的物品, 从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。
1 ≤ n ≤ 100I
1 ≤ wi, vi ≤ 100
1 ≤ W ≤ 10000
输入:
第一行物体个数n
第二行重量
第三行价值
第四行背包承装W
输出:
最大价值
样例:
输入:
4
2 1 3 2
3 2 4 2
5
输出:
7 (选择第0, 1, 3号物品)
(2)思路及其代码实现
思路一:动态规划
A、设初始总的最大价值为0 + f(W, 0)。
[f(W, 0)指的是从0号物品开始选择总重量≤W的总价值]
B、对于物品0,若选择,则总价值有 v0 + f(W - w0, 1);若不选择,则总价值有 0 + f(W, 1),此时当前的最大价值=max{v0 + f(W - w0, 1), 0 + f(W, 1)} ;
==>>
dp公式:dp[i][j] = 0 , (j == 0)
dp[i][j] = max{v[i] + dp[i - 1][j - w[i]], 0 + dp[i - 1][j]} (j > 0)
其中,i:表示行,代表可选第0——i个物品; j:表示列,代表背包剩余容量j;
tips: 按行解出dp[ ][ ],因为下一行的解依赖上一行的解。
/**
* way01——动态规划dp解法
* @param w
* @param v
* @param W
* @return
*/
private static int dp(int[] w,int[] v,int W) {
int[][] dp = new int[w.length][W + 1];
// 初始化dp表的第一行
for (int i = 0; i < W + 1; i++) {
if (i >= w[0]) {
//如果当前容量i装得下物体0
dp[0][i] = v[0];
}
}
// 剩余行
for (int i = 1; i < w.length; i++) {
//行,代表可选第0——i个物品
for (int j = 0; j < W + 1; j++) {
//列,代表背包剩余容量j
if (j >= w[i]) {
dp[i][j] = Math.max(v[i] + dp[i-1][j-w[i]], dp[i-1][j]);
}
}
}
return dp[v.length-1][W];
}
思路二:深度优先搜索DFS
/**
* way02——深度优先搜索DFS O(2^n)
* 遍历此搜索二叉树的所有分支,每个非叶子结点值==左右孩子的较大值
* @param w 重量数组
* @param v 价值数组
* @param W 背包承重
* @param current 当前判断物品下标 从0开始
* @return
*/
private static int dfs(int