文章目录

  • 0. 前言
  • 1. 01背包+求方案数+思维

0. 前言

相关:

  • [背包] 背包问题算法模板(模板)

1. 01背包+求方案数+思维

12. 背包问题求具体方案


求方案数也是背包问题、dp 的一大考点。本题仅以 01 背包为例。其实所有的 dp 问题都可以求出来状态转移的具体方案。所有的状态构成图,针对于 min 转移的话,其实就是求最短路路径,针对 max 转移的话,其实就是求最长路路径。

状态转移方程为 f[i][j] = max(f[i-1][j], f[i-1][j-vi]+wi),其实就是决策出每个 i 的状态转移到底是从第一项还是第二项转移过去的。那么当我们求完之后倒着推一遍就能得到转移过来的最短路径了。 例如,答案 f[n]m] 转移情况有三种:

  • f[n][m]=f[n-1][m] 的时候,不选第 n 个物品,可以得到最大价值
  • f[n][m]=f[i-1][j-vi]+wi,选择第 n 个物品,可以得到最大价值
  • f[n][m]=f[i-1][j-vi]+wi 或者 f[n][m]=f[n-1][m],第 n 个物品选不选都可以得到最大价值

注意:

  • 需要使用两维状态,需要 i 这个序号,最后需要输出
  • 因为本题需要按字典序输出,那么肯定是从第 1 个物品开始考虑
    • f[1][m]=f[2,m-v[1]]+w[1] 选第一个能得到最优解
    • f[1][m]=f[2,m],不选第一个能得到最优解
    • f[1][m]=f[2,m-v[1]]+w[1]=f[2,m] 选不选第一个都能得到最优解。但还是选第一个,因为它字典序最小
  • 但是,得到字典序路径是需要反着倒推的,所以枚举物品的时候就从第 n 个物品枚举到第 1 个物品,这样逆序枚举。求出来的当前背包最大价值应为 f[1][m],这样是很灵活方便的
    • 代码一定理解透本质,灵活多变

代码:

#include <iostream>
#include <algorithm>using namespace std;const int N = 1005;int n, m;
int v[N], w[N];
int f[N][N]; int main() {cin >> n >> m;for (int i = 1; i <= n; ++i) cin >> v[i] >> w[i];for (int i = n; i >= 1; --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][j], f[i + 1][j - v[i]] + w[i]);}// 在此,f[1][m]就是最大数量int j = m;for (int i = 1; i <= n; ++i) if (j >= v[i] && f[i][j] == f[i + 1][j - v[i]] + w[i]) {cout << i << ' ';j -= v[i];}return 0;
}

一般的,开辟一个数组专门用以记录状态转移过程也能完成状态记录。这是更为一般的方式。

在此,有递归、非递归两种写法。参考大佬题解:背包问题求具体方案(递归版本)

#include <iostream>
#include <algorithm>using namespace std;const int N = 1005;int n, m;
int v[N], w[N];
int f[N][N], g[N][N];// 递归打印,参考:https://www.acwing.com/solution/content/19760/
void print(int x,int y)
{if(x == n + 1) return;int k = way[x][y];//判断是否选择了第x件物品if(k) cout<<k<<' ';//在递归函数的上面为由根节点到叶子节点进行操作print(x+1,y-v[k]);//在递归函数的下面进行操作,为叶子节点遍历完了,回溯由子节点到根节点进行操作}int main() {cin >> n >> m;for (int i = 1; i <= n; ++i) cin >> v[i] >> w[i];for (int i = n; i >= 1; i --) for (int j = 0; j <= m; j ++) {f[i][j] = f[i + 1][j];if (j >= v[i]) {if (f[i][j] <= f[i + 1][j - v[i]] + w[i]) { f[i][j] = max(f[i + 1][j], f[i + 1][j - v[i]] + w[i]);g[i][j] = i;}}}// 递归// print(1, m);// 非递归int j = m;for (int i = 1; i <= n; ++i) {if (j >= v[i]) {if (g[i][j]) {cout << g[i][j] << ' ';j -= v[i];}}}return 0;
}

[01背包] 背包问题求具体方案(01背包+求方案数+思维)相关推荐

  1. 二维背包问题(二维0-1背包)

    二维0-1背包问题 问题描述 算法思路与代码实现 方法一:普通动归方法 方法二:空间优化法 代码1:方法一 从n个物品中的第1个物品开始考虑(从前往后考虑). 从n个物品中的第n个物品开始考虑(从后往 ...

  2. 背包问题详解:01背包、完全背包、多重背包

    参考链接: http://www.cnblogs.com/fengty90/p/3768845.html http://blog.csdn.net/mu399/article/details/7722 ...

  3. 背包九讲系列1——01背包、完全背包、多重背包

    我在进行一些互联网公司的技术笔试的时候,对于我来说最大的难题莫过于最后的那几道编程题了,这对算法和数据结构有一定程度上的要求,而"动态规划"又是编程题中经常出现的算法类型,并且对于 ...

  4. 背包算法(一)-01背包-史上最详细解答

    背包算法(一)-01背包-史上最详细解答 1. 题目 2. 分析 2.1 状态表示 2.2 状态计算 3. 实现 4. 优化 5. 测试 1. 题目 问题描述:有n件物品和容量为m的背包,给出i件物品 ...

  5. [01背包] 宠物小精灵之收服(01背包+二维费用背包+思维)

    文章目录 0. 前言 1. 01背包裸题 0. 前言 相关: [背包] 背包问题算法模板(模板) 1. 01背包裸题 1022. 宠物小精灵之收服 每个精灵仅被收服一次,故可以考虑 01 背包,是典型 ...

  6. 01背包与完全背包(动态规划)(01背包)

    题目描述 一个旅行者有一个最多能负载m公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分 输入格式 第一行:两个整数,M(背包容量,M<=200)和N(物品数量, ...

  7. 01背包问题分支限界java_分支限界法-01背包问题

    1.分支限界法介绍 分支限界法类似于回溯法,也是在问题的解空间上搜索问题解的算法.一般情况下,分支限界法与回溯法的求解目标不同.回溯法的求解目标是找出解空间中满足约束条件的所有解:而分支限界法的求解目 ...

  8. c语言 用回溯算法解决01背包问题,回溯法解决01背包问题

    <回溯法解决01背包问题>由会员分享,可在线阅读,更多相关<回溯法解决01背包问题(21页珍藏版)>请在人人文库网上搜索. 1.回溯法解决01背包问题,回溯法解决01背包问题, ...

  9. 01型背包问题解题总结(二维)

    前言:01型背包问题(一维)的链接: https://blog.csdn.net/qq_56430444/article/details/118157798 完全背包问题链接: https://blo ...

最新文章

  1. 操纵神经元构造后门,腾讯朱雀实验室披露AI模型新型攻击手法
  2. 批处理文件中判断是否64位系统
  3. 快速上手RaphaelJS--RaphaelJS_Starter翻译(一)
  4. java异步框架feed,Java:IO流里面的BuffeedReader
  5. 去掉“3_人民日报语料”中每行前边的数字编号,改成“1, 2,......”
  6. python中os.system.获取输出信息_python中os.system()的返回值
  7. 设置linux英文环境,英文Linux里中文和日文用户环境设置
  8. 捕获Java堆转储的7个选项
  9. 支付宝生活号,同时出现俩网址,到底哪个真哪个假?
  10. matlab green函数,地基土的传Green函数编辑中……
  11. C语言判断素数的几种方法
  12. django基础知识总结
  13. 如何制作简单的html静态网页
  14. Vue----组件注册
  15. 结合可变形注意力的视觉Transformer
  16. (二)WebService之调用soap服务
  17. shell sftp 命令大全
  18. 高德地图-初始化的时候获取行政区边界和中心点
  19. NVM - Nodejs的版本管理工具安装和使用
  20. Android局域网对讲,基于Android系统机器人局域网对讲方法与流程

热门文章

  1. SecureCRT目录乱码
  2. 计算机中的表示方法,计算机应用基础第三章计算机中信息的表示方法
  3. 耍耍VSCode1 - 1分钟变身小霸王
  4. html的网页怎么打包成网址,如何将网址打包成APP?(详细教程)
  5. 【Linux】win10/ubuntu 双系统安装遇到 gnu grub 2.0.3 或者 error symbol ‘grub_calloc‘ not found 的解决方法
  6. 【每日早报】2019/11/05
  7. 十二 ES json数据格式
  8. 删除oracle中的一列数据,Oracle删除表数据
  9. 蓝桥杯2N皇后问题-使用Python实现
  10. 扫雷游戏的实现步骤和代码