资料:B站背包九讲:https://www.bilibili.com/video/BV1qt411Z7nE
对应训练题:https://www.acwing.com/problem/
01背包问题
此问题解法来自背包九讲,
未优化
状态:f[i][j]表示前 i 个物品,总体积为 j 的最大价值
所以就有两种方式,选当前物品放入背包和不选当前物品放入背包
即不选当前物品放入背包 :f[i-1][j],直接拿上一个物品的价值即可,体积不变
或者选当前物品放入背包,:f[i-1][j-v[i]]+w[i],需要减去当前物品的体积 再加上当前物品价值
当前i,j即取二者最大值
状态转移:f[i][j] = Math.max(f[i-1][j],f[i-1][j-v[j]]+w[i])
初始条件,f[0][0]=0
具体代码
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
int[] Value = new int[N+1];
int[] Weight = new int[N+1];
//从1开始,0代表背包内容为0时的最大价值
for(int i = 1;i<=N;i++){
Weight[i] = sc.nextInt();
Value[i] = sc.nextInt();
}
System.out.println(packageQuestion2(N,M,Weight,Value));
}
public static int packageQuestion(int N,int M,int[] Weight,int[] Value){
// dp状态方程
int[][] dp = new int[N+1][M+1];
// dp[i][j]表示前i个物品,体积是j的,最大的总价值
//遍历所有物品
for(int i = 1;i<=N;i++){
// 从0开始遍历背包容量
for(int j = 0;j<=M;j++){
// dp[i][j]表示前i个物品,体积是j的,最大的总价值
//如果当前背包容量大于等于当前元素的体积,就可以装
if(j>=Weight[i]){
//dp[i-1][j]表示不选当前元素,表示当前容量下前i个元素的价值等于第i-1个元素的价值
//dp[i-1][j-Weight[i]]+Value[i]表示选择当前元素,即:当前元素针对当前背包大小的价值等于(背包现容量
//-当前元素的体积)的价值加上当前元素的价值,
//这里dp[i-1][j-Weight[i]]+Value[i],为啥要用i-1的原因是,如果用当前i,其实算当前i的时候已经对当前元素进行处理了,
//如果用i,会处理两次,用i-1才是处理针对当前层的上一层的最优
//上面是通俗一点的解释,真正的解释是:dp状态转移方程 都是由上一层来递推到当前层而不是直接在当前层上处理当前层的信息
dp[i][j]