背包问题

0-1背包问题

1. 题目

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

2.基本思路

01背包问题的特点是每种物品仅有一件,可以选择放或者不放。用动态规划做。
定义状态:dp[i][v]表示前i件物品恰好放入容量为V的背包中,可以获得的最大价值,
状态转移方程:dp[i][v]= max(dp[i-1][v], dp[i-1][v- Wi]+Wi)也就是说,“将前i件物品放入容量v的背包中”这个子问题,只考虑第i件物品放与不放,

  • 如果不放,该问题转换为”前i-1件物品放入容量为v的背包中“,价值为dp[i-1,v],
  • 如果放,该问题转换为“前i-1件物品放入v-Ci的背包中“,价值为dp[i-1,v-Ci]+Wi;

初始值:dp[0,0…V] = 0;
伪代码

     dp[0,0...V] <- 0;
      for i <- 1 to N
       	for v<-Ci to V
       		dp[i][v]= max{dp[i-1][V], dp[i-1][V-Ci]+Wi}

时间复杂度为O(VN),空间复杂度为O(VN)

3. 优化空间复杂度为O(V)

针对外层循环i<- 1…N,保证每次得出二维数组dp[i,0…V],如果只用一个数组dp[0…V]可以保证每次内层循环结束后dp[v]是dp[i,v]??
由于状态转移方程中需要用到dp[i-1,v],dp[i-1, v-Ci],可以将内层循环以v<- V … 0 的递减顺序计算dp[v],这样可以保证计算dp[v]时dp[v-Ci]保存的是状态dp[i-1,v-Ci]的值。
伪代码

dp[0,0...V] <- 0;
 for i <- 1 to N
      	for v<- V to Ci
     		dp[v]= max{dp[V], dp[V-Ci]+Wi}

4. 初始化细节

  1. 如果问题是“恰好装满背包”时的最优解:除了dp[0] = 0,其他的dp[1…V] = 负无穷大,原因在于“只有容量为0的背包在什么也不装且价值为0的情况下恰好装满,其他容量的背包均没有合法的解
  2. 如果题目中只是要求价值最大化,不要求背包装满:dp[0…V] = 0, 原因在于背包并非要求装满,那么任何容量的背包都有一个合法解“什么都不装”

5. 还可以继续优化

针对内层循环,在背包空间为0~max(Ci,前i-1 件物品容量之和),价值都不会得到改变
伪代码

 dp[0,0...V] <- 0;
 for i <- 1 to N
     for v<- V to max(Ci,V-后(N-i)件物品容量之后)
      	dp[v]= max{dp[V], dp[V-Ci]+Wi}

6.例题

例题一——Leetcode416.分割等和子集

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值