0-1背包问题,以及空间优化

什么是0-1背包问题?

有一个容量为 N 的背包,要用这个背包装下物品的价值最大,这些物品有两个属性:体积 w 和价值 v。

定义一个二维数组 dp 存储最大价值,其中 dp[ i ][ j ] 表示前 i 件物品体积不超过 j 的情况下能达到的最大价值。设第 i 件物品体积为 w,价值为 v,根据第 i 件物品是否添加到背包中,可以分两种情况讨论:

  • 第 i 件物品没添加到背包,总体积不超过 j 的前 i 件物品的最大价值就是总体积不超过 j 的前 i - 1 件物品的最大价值,dp[ i ][ j ] = dp[ i - 1 ][ j ]。
  • 第 i 件物品添加到背包中,dp[ i ][ j ] = dp[ i - 1 ][ j - w ] + v。

第 i 件物品可添加也可以不添加,取决于哪种情况下最大价值更大。因此,0-1 背包的状态转移方程为:
在这里插入图片描述

// W 为背包总体积
// N 为物品数量
// weights 数组存储 N 个物品的重量
// values 数组存储 N 个物品的价值
public int knapsack(int W, int N, int[] weights, int[] values) {
   
    int[][] dp = new int[N + 1][W + 1];
    for (int i = 1; i <= N; i++) {
   
        int w = weights[i - 1], v = values[i - 1];
        for (int j = 1; j <= W; j++) {
   
            if (j >= w) {
   
                dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w] + v);
            } else {
   
                dp[i][j] = dp[i - 1][j];
            }
        }
    }
    return dp[N][W];
}
2.空间优化

将二维数组降为一维数组,一维数组就必须要逆序遍历。因为:f[i][v]与f[i - 1][v]以及f[i - 1][v - c[i]]有关的。当我们逆序遍历的时候,我们数组前一部分,是上一轮i - 1遍历的结果,刚好符合要求;而如果我们顺序遍历的话,我们就会把i - 1轮的数据给覆盖掉。即:数组前面的f[0] f[1] … f[v - 1] 都已经改变过,里面存的都不是 i - 1时刻的值。因此,必须采用逆序遍历的方式。

3.举一个例子
设有3件物品 ,背包能容纳的总重量为10
i=1,2,3

物品号         重量(c)          价值(w)
i=1             4                 5

i=2             7                 9

i=3             5                 6
f[v]=max{
    f[v],f[v-c[i]]+w[i] }
如果v是顺序递增 i=1时,v=4~10 (因为v要至少大于等于c[i]嘛 不然减出个负数没意义)
原先的:  f[0]=0 f[1]=0 f[2]=0 f[3]=0 f[4]=0 f[5]=0 f[6]=0 f[7]=0 
f[8]=0 f[9]=0  f[10]=0
----------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值