目录
完全背包问题的初始化与 01 背包的初始时相同:
第一行需要初始化,
第一列不需额外初始化, 在填表时一同填入即可(存在条件判定, 不会发生越界)
1. 【模板】完全背包
1.1 算法原理
- 状态表示:
dp[i][j] : 从前 i 个数中选, 总体积不超过 j , 所有选法中, 最大价值(第一问)
dp[i][j] : 从前 i 个数中选, 总体积等于 j , 所有选法中, 最大价值(第二问)
- 状态转移方程:
dp[i][j] = max(dp[i - 1][j], dp[i][j - v[i]] + w[i])
- 初始化
如下图.
- 建表顺序:
从上往下每一行,
从左往右每一列
- 返回值
1) dp[n][V]
2) dp[n][V] == -1 ? 0 : dp[n][V]
1.2 算法代码
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(); // 物品个数
int large = in.nextInt(); // 背包体积
int[] V = new int[n];
int[] W = new int[n];
for(int i = 0; i < n; i++) {
V[i] = in.nextInt();
W[i] = in.nextInt();
}
// 第一问
int[][] dp = new int[n + 1][large + 1];
for(int i = 1; i <= n; i++) {
for(int j = 0; j <= large; j++) {
dp[i][j] = dp[i - 1][j];
if(j >= V[i - 1]) dp[i][j] = Math.max(dp[i][j], dp[i][j - V[i - 1]] + W[i - 1]);
}
}
System.out.println(dp[n][large]);
// 第二问
// 初始化
for(int j = 1; j <= large; j++) dp[0][j] = -1;
// 填表
for(int i = 1; i <= n; i++) {
for(int j = 0; j <= large; j++) {
dp[i][j] = dp[i - 1][j];
if(j >= V[i - 1] && dp[i][j - V[i - 1]] != -1)
dp[i][j] = Math.max(dp[i][j], dp[i][j - V[i - 1]] + W[i - 1]);
}