zoukankan      html  css  js  c++  java
  • 【LeetCode & 剑指offer刷题】动态规划与贪婪法题16:背包问题总结

    【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

    背包问题总结

    背包问题
     
    背包问题 (Knapsack problem x ) 有很多种版本,常见的是以下三种:
    • 0-1 背包问题 (0-1 knapsack problem):每种物品只有一个
    • 完全背包问题 (UKP, unbounded knapsack problem):每种物品都有无限个可用
    • 多重背包问题 (BKP, bounded knapsack problem):第 i 种物品有 n[i] 个可用
     
    0-1 背包问题
    0-1背包中一种物体只有一个,放入数量为0或者1
    定义状态 dp[i][j],表示“把前 i 种物品装进重量限制为 j 的背包可以获得的最大价值
    v[i]表示物品i的价值,w[i]表示物品i的重量,j为背包的重量限制
    0/1背包问题状态转移方程便是:
       dp[i][j] = max{dp[i − 1][j],  dp[i − 1][j − w[i]] + v[i]}
        两项分别代表物品i不选择或者选择的情况 (减去的代表选择的)
    时间复杂度是O(nb),空间也是O(nb),假设有n种物品,重量限制为b
     
     
    可以简化为:
       d[j]=max{d[j],d[j-w[i]]+v[i]};
    注意:遍历j时务必从右到左,因为d[j]只依赖于上一阶段的结果,从右到左避免覆盖上阶段有用结果
     
     
    完全背包问题
    完全背包中一种物体可以有多个,可以放满背包为止
    完全背包问题状态转移方程是:
       dp[i][j] = max{dp[i − 1][j],  dp[i][j − w[i]] + v[i]}
    两项分别代表物品i不选择或者选择,由于对物品i没有限制,故后一项为dp[i]而非上面的dp[i-1]
     
    或用以下递推式(上面的效率要高一点):
    dp[i][j] = max( dp[i-1][j-k*w[i]] + k*v[i] ),   k为选择物品的个数, k=0,1,2...j/w[i] (0 ≤ k ∗ w[i] ≤ j)
    基于前i-1个物品,在选择不同个数的物品i的方案中选择最大的那个
    (和问题coin change 比较相似)
     
    可以简化为:
       d[j] = max{d[j], d[j-k*w[i]] + k*v[i]}
    注意:遍历j时务必从右到左,原因同上
     
    多重背包问题
    多重背包中一种物体可以有多个,个数有人为限定(也不能超过背包容量)
    多重背包问题状态转移方程是:
    dp[i][j] = max( dp[i−1][j−k∗w[i]] + k∗v[i] )    0 ≤ k ≤ n[i],0 ≤ k ∗ w[i] ≤ j
    n[i]为物品i限制的个数
    基于前i-1个物品,在选择不同个数的物品i的方案中选择最大的那个
     
    可以简化为:
       d[j] = max{d[j], d[j-k*w[i]] + k*v[i]}
    注意:遍历j时务必从右到左,原因同上
     
    参考:
  • 相关阅读:
    快速排序和随机化快排学习
    P1330 封锁阳光大学 DFS
    P2577 [ZJOI2005]午餐 状压DP
    M. Subsequence 南昌邀请赛
    P1441 砝码称重 DFS回溯+DP
    P2661 信息传递 二分图的最小环
    P1196 [NOI2002]银河英雄传说 带权并查集
    P2024 [NOI2001]食物链 并查集
    F. Shovels Shop 背包DP
    P1514 引水入城 DFS
  • 原文地址:https://www.cnblogs.com/wikiwen/p/10229403.html
Copyright © 2011-2022 走看看