题目描述:
下面提供了三种解法:
(1)无记忆性递归
(2)有记忆性递归
(3)动态规划
三种解法全部放在了一个代码片里面
public class Practice_01背包问题 {
static int[] w = {2, 1, 3, 2};//重量表
static int[] v = {3, 2, 4, 2};//价值表
static int n = 4;//物品数量
static int W = 5;//背包的称重极限
static int[][] rec;//备忘录
public static void main(String[] args) {
int ww1 = W;
int ans1 = dfs(0, ww1);
rec = new int[n][ww1 + 1];
System.out.println(ans1);
int ww2 = W;
int ans2 = dfs_1(0, ww2);
System.out.println(ans2);
System.out.println(dp());
}
private static int dfs(int i, int ww) {
if (ww <= 0) return 0;//装不进去
if (i == n) return 0;//没有可选择的了
int v2 = dfs(i + 1, ww);//不选择当前物品
if (ww >= w[i]) {
int v1 = v[i] + dfs(i + 1, ww - w[i]);//选择当前物品;
return Math.max(v1, v2);
} else {
return v2;
}
}
//记忆型递归
private static int dfs_1(int i, int ww) {
if (ww <= 0) return 0;//装不进去
if (i == n) return 0;//没有可选择的了
//计算之前进行查询,有就直接返回
if (rec[i][ww] > 0) return rec[i][ww];
int v2 = dfs(i + 1, ww);//不选择当前物品
int ans;
if (ww >= w[i]) {
int v1 = v[i] + dfs(i + 1, ww - w[i]);//选择当前物品;
ans = Math.max(v1, v2);
} else {
ans = v2;
}
//计算之后进行存储
rec[i][ww] = ans;
return ans;
}
private static int dp() {
int[][] dp = new int[n][W + 1];
//初始化dp数组第一行
for (int i = 0; i < W + 1; i++) {
if (i >= w[0]) dp[0][i] = v[0];
else dp[0][i] = 0;
}
for (int i = 1; i < n; i++) {
for (int j = 0; j < W + 1; j++) {
if (j >= w[i]) {//要得起 j指的是剩余容量
int v1 = v[i] + dp[i - 1][j - w[i]];
int v2 = dp[i - 1][j];
dp[i][j] = Math.max(v1, v2);
} else {//要不起
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[n - 1][W];
}
}