zoukankan      html  css  js  c++  java
  • 「算法笔记」背包问题解题思路

    本文中,约定物品个数为 (n),背包的最大价值为 (m)

    多重背包问题的转化

    1. 可以通过把一个多重背包中的物品拆成多个 (01) 背包中的物品(每次大小翻倍,最后余下的单独拆出一个物品)。插入一个物品的复杂度为 (O(m imes log m))。比较好写,较常用。
    2. 可以使用单调队列来优化 ( ext{DP}),插入一个物品的复杂度为 (O(m))。比较难写,卡常时用。

    完全背包的特殊性质

    1. 对于物品集合 (A) 和物品集合 (B)(A igcup B) 的完全背包就等于 (A) 的完全背包和 (B) 的完全背包合并的结果。
    2. 如果有多个大小相同的物品,肯定是取价值最大的物品最优。

    任意背包的通用思路

    1. 合并两个背包的时间复杂度是 (O(m^2)),而加入一个物品的复杂度是 (O(m)) 左右。于是解决问题时,我们尽量避免合并两个背包。
    2. 如果只计算每种体积是否可以达到,可以用 ( ext{bitset}) 进行常数优化。
    3. 如果计算方案数,背包可以删除物品,否则不行。

    例题试炼

    例题一:

    (q) 个询问。每次问区间 ([l, r]) 的完全背包。强制在线。

    (n, q le 10^5, m le 30)

    线段树维护区间大小为 (k (1 le k le m)) 的最大价值,对于每个询问做完全背包即可。时间复杂度 (O(n imes log n imes m + q imes m^2))

    例题二:

    询问对于 (1 le i le n),除了第 (i) 个物品以外的物品的 (01) 背包。

    (n, m le 3000)

    分治,递归到左半边时加入右半边的物品,递归到右半边时加入左半边的物品。时间复杂度 (O(n imes log n imes m))

    例题三:

    一棵树,每个点都是物品。(q) 次询问,每次询问两点路径 (01) 背包。

    (n, q le 10^5, m le 30)

    直接树上倍增需要合并背包,效率低下。考虑点分治,对于 ( ext{DFS}) 只需加单个物品,处理询问时只需合并两个背包。时间复杂度 (O(n imes log n imes m + q imes m^2))

    “记录算法学习的点点滴滴”
  • 相关阅读:
    ADO.Net对Oracle数据库的操作(转)
    代码反思(1)
    继承与多态
    存储过程
    linux学习流程及内容概括
    Linux下终端快捷键
    查找算法
    epoll解读
    TCP/udp编程
    如何学习嵌入式
  • 原文地址:https://www.cnblogs.com/blog-of-xianglingao/p/10409814.html
Copyright © 2011-2022 走看看