01背包 1维 (滚动数组)

这里先说一下二维的。

///01背包
///设物品有n件物品,背包容量为w
int w[];     ///代表n件物品的价值
int pw[];    ///代表n件物品各占的容量

int f[n+50][w+50];   ///最优解二维数组
///f[i][j]数组 代表存i件物品在容量为j的背包中得到的价值

void package_01(){
    for(int i=0;i<=n;i++) f[i][0]=0;
    for(int j=0;j<=c;j++) f[0][j]=0;    ///初始化,       ///若要求恰好装满,除这两个初始化外,其他值全部赋值为 -0x3f3f3f3f,(这样能够保证最后恰好装满)
                                                         ///

    for(int i=1;i<=n;i++){      ///有点枚举的感觉,枚举n件物品
        for(int j=pw[i];j<=c;j++){  ///与上同理
            if(f[i-1][j-pw[i]]+w[i]>f[i-1][j])  ///i-1件物品放入j-pw[i]容量的价值+w[i]的价值(即为放) 与 i-1件物品放入j容量(即为不放) 的所得价值比较
                f[i][j]=f[i-1][j-pw[i]]+w[i];
            else f[i][j]=f[i-1][j];
        }
    }
    printf("%d\n",f[n][w]);     ///f[n][w]即为最优解
}

二维的状态转移方程

f[i][j] = max \left\{\begin{matrix} f[i-1][j-pw[i]] + w[i] \\ f[i-1][j] \end{matrix}\right. 

很显然,f[i][*]  只与  f[j-1][*] 的状态有关  所以这里可以有空间上的优化。

先看代码:

memset(dp, 0, sizeof(dp));
for(int i=0; i<n; i++){
    for(int j=c; j>=pw[i]; j--){
        dp[j] = max(dp[j], dp[j-pw[i]]+w[i])
    }
}

对于外层的循环,每进行一次,dp[] 保存的状态都还是  i - 1 时候的dp[] ,所以在第二层循环使用的时候就相当于使用的是

dp[i - 1][j - pw[i]] + w[i] 与 dp[i-1][j] ..

并且,状态转移方程,每一次推导 dp[i][j] 是通过 dp[i-1][j-w[i]] 来推导的,所以一维数组中j的扫描顺序应该从大到小(c 到 0),否者前一次循环保存下来的值将会被修改,从而造成错误。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值