博客
关于我
[背包] 背包问题算法模板(模板)
阅读量:569 次
发布时间:2019-03-09

本文共 2485 字,大约阅读时间需要 8 分钟。

背包问题是系统学习动态规划的重要研究课题,其核心在于如何高效地解决位于有限容量中的最大价值选择问题。以下将从01背包延伸至多种背包模型,并介绍相应的优化方法和解决方案。

01背包问题

特点

  • 每个物品只能使用一次。
  • 需要考虑容量受限的最大化价值的选择问题。

逐步思路

  • 状态定义:设 f[i][j] 表示前 i 个物品,总体积不超过 j 时的最大价值。
  • 状态转移
    • 不选第 i 个物品f[i][j] = f[i-1][j]
    • 选第 i 个物品f[i][j] = max(f[i-1][j], f[i-1][j-v[i]] + w[i])
  • 空间优化
    • 使用滚动数组,仅保存当前层状态,更新至 j 时只需保存当前层数据。
  • 时间优化
    • 通过一维数组和逆序体积枚举,进一步降低空间复杂度。
  • 完全背包问题

    特点

    • 每个物品可以无限次地使用。

    思路

    • 状态定义:与01背包类似,f[i][j] 表示前 i 个物品,总体积不超过 j 时的最大价值。
    • 状态转移f[i][j] = max(f[i-1][j], f[i][j-v[i]] + w[i])
    • 优化方法
      • 滚动数组优化,采用逆序体积枚举策略,计算 f[j]

    多重背包问题

    特点

    • 每个物品有数量限制,必须不超过给定的最大数量。

    思路

    • 状态定义:类似01背包 f[i][j]
    • 状态转移:考虑不同数量的选择,如 f[i][j] = max(k=1 到 s[i], f[i][j-k*v[i]] + k*w[i])

    优化方法

    • 二进制优化:将物品的数量拆分成二进制倍增,增加效率。
    • 单调队列优化:对复杂的背包问题进行空间和时间的优化。

    分组背包问题

    特点

    • 物品分为若干组,每组只能选择一件物品。

    思路

    • 状态定义f[i][j] 表示前 i 组物品,总体积不超过 j 时的最大价值。
    • 状态转移:分组内的物品选择进行最大化。

    护身背包问题

    特点

    • 物品具有依赖性,形成树形结构。
    • 需要考虑树形的最优选择。

    思路

    • 采用动态规划和树形处理结合分组背包,分别处理每个子树。

    工具与代码

    通过以上方法,可以实现多种背包问题验证,并对结果进行分析。各优化方法的实现代码通常采用逆序枚举体积和空间优化技巧,能显著提升效率。

    各类背包问题的解决方案代码如下:

  • 01背包代码
  • #include 
    #include
    using namespace std;const int N = 1005;int v[N], w[N];int f[N][N];int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> v[i] >> w[i]; for (int i = 1; i <= n; ++i) { for (int j = 0; j <= m; ++j) { f[i][j] = f[i-1][j]; if (j >= v[i]) { f[i][j] = max(f[i-1][j], f[i-1][j - v[i]] + w[i]); } } } cout << f[n][m] << endl; return 0;}
    1. 完全背包代码
    2. #include 
      #include
      using namespace std;const int N = 1005;int n, m;int v[N], w[N];int f[N];int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> v[i] >> w[i]; for (int i = 1; i <= n; ++i) { for (int j = v[i]; j <= m; ++j) { if (f[j] < f[j - v[i]] + w[i]) f[j] = f[j - v[i]] + w[i]; } } cout << f[m] << endl; return 0;}
      1. 多重背包代码
      2. #include 
        #include
        using namespace std;const int N = 205;int n, m;int v[N], w[N], s[N];int f[N];int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> v[i] >> w[i] >> s[i]; for (int i = 1; i <= n; ++i) { for (int j = 0; j <= m; ++j) { for (int k = 0; k * v[i] <= j; ++k) { if (k > s[i]) break; if (f[j] < f[j - k*v[i]] + k*w[i]) f[j] = f[j - k*v[i]] + k*w[i]; } } } cout << f[m] << endl; return 0;}

        多种背包问题的解决方案均可通过优化策略对空间和时间复杂度进行控制,达到高效解决问题的目的。

    转载地址:http://iuepz.baihongyu.com/

    你可能感兴趣的文章
    Mysql8.0以上重置初始密码的方法
    查看>>
    mysql8.0新特性-自增变量的持久化
    查看>>
    Mysql8.0注意url变更写法
    查看>>
    Mysql8.0的特性
    查看>>
    MySQL8修改密码报错ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
    查看>>
    MySQL8修改密码的方法
    查看>>
    Mysql8在Centos上安装后忘记root密码如何重新设置
    查看>>
    Mysql8在Windows上离线安装时忘记root密码
    查看>>
    MySQL8找不到my.ini配置文件以及报sql_mode=only_full_group_by解决方案
    查看>>
    mysql8的安装与卸载
    查看>>
    MySQL8,体验不一样的安装方式!
    查看>>
    MySQL: Host '127.0.0.1' is not allowed to connect to this MySQL server
    查看>>
    Mysql: 对换(替换)两条记录的同一个字段值
    查看>>
    mysql:Can‘t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock‘解决方法
    查看>>
    MYSQL:基础——3N范式的表结构设计
    查看>>
    MYSQL:基础——触发器
    查看>>
    Mysql:连接报错“closing inbound before receiving peer‘s close_notify”
    查看>>
    mysqlbinlog报错unknown variable ‘default-character-set=utf8mb4‘
    查看>>
    mysqldump 参数--lock-tables浅析
    查看>>
    mysqldump 导出中文乱码
    查看>>