01背包

题目

有N件物品和一个容量为V的背包。放入第i件物品耗费的费用是Ci,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大。

基本思路

最基础的背包问题,特点是:每种物品仅有一件,可选择放或不放

用子问题定义状态:即F[i][v]=max(F[i-1][v],F[i-1][v-Ci]+Wi)

详细解释一下该方程:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么可以转化为一个只和前i-1件物品相关的问题。

1.若不放第i件物品,那么问题就转化“前i-1件物品放入容量为v的背包中”,价值为F[i-1][v]

2.如果放第i件物品,那么问题就转化为"前i-1件物品放入剩下的容量为v-Ci的背包里",此时能获得的价值就是F[i-1][v-Ci]再加上通过放入第i件物品获得的价值Wi,F[i-1][v-Ci]+Wi

for(i=1;i<=N;i++)
{
   for(v=1;v<=V;v++)
   {
      if(v<C[i]) //C[i]是第i件物品的费用
         d[i][v]=d[i-1][v];
      else
         d[i][v]=max(d[i-1][v],d[i-1][v-C[i]]+W[i]);  //W[i]是第i件物品的价值
   }
}

空间复杂度优化 

    其实数组每次写入一行数据都是根据上一行的数据进行写入,不需要用二维数组,可以用一维数组,每次根据自身进行更新即可,重点是F[i-1][v - C[i]]这个数据的意思是我要在表中上一行找比v小的数据,那换成一维的话,我找的是自身(只有一行,没有上一行)v左边的数据,这个数据必须保证是上一次(i-1)写入的,肯定不能从左向右写入数据,那样的话F[i-1][v - C[i]] 对应的就是这一次(i)写入的,上一次数据没有利用就丢失了,所以v循环应该从V到1,从右向左向一维数组写入数据。

for(i=1;i<=N;i++)
{
   for(v=V;v>=C[i];v--)
   {
      if(v>=C[i])
         d[v]=max(d[v],d[v-C[i]]+W[i]);
   }
}

初始化的细节

求最优解的背包问题中,其实有两种不同的问法。

1.恰好装满背包时的最优解。在初始化时,除了F[0][v],F[i][0]=0,其它F[i][v]均设为负无穷,这样就可以保证最终得到的F[N][V]是一种恰好装满背包的最优解。

2.没有要求必须把背包装满,而只是希望价值尽量大,初始化时F[i][v]全部设为0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值