【动态规划】—— 背包问题
背包问题的分类
01背包问题
输入样例
4 5 1 2 2 4 3 4 4 5
输出样例:
8
在求选 第 i 个物品的状态转移方程的时候,我们可以取出 的最大值再加上 w[i]
不选第 i 个物品的话,状态转移方程就是
#include <iostream>
#include <cstring>
using namespace std;const int N = 1010;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 = 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][j], f[i - 1][j - v[i]] + w[i]);}cout << f[n][m] << endl;return 0;
}
从二维优化到一维
通过 DP 的状态转移方程,我们发现,每一阶段的 i 的状态只与上一阶段的 i-1 的状态有关。在这种情况下,可以使用称为“滚动数组”的优化方法,降低时间开销。
因为 这里的
一定比
更早计算出来,所以
计算得到的是第 i 层的,而在我们上述的 DP 方程中,所用的是第 i - 1 层的数据,所以如果是从小到大遍历体积的话,会出现 “数据污染” 的情况。所以体积的枚举要从大到小来枚举。
一维优化代码实现
#include <iostream> #include <cstring> using namespace std;const int N = 1010;int n, m; int v[N], w[N]; int f[N];int main() {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 = m; j >= v[i]; j -- ){f[j] = max(f[j], f[j - v[i]] + w[i]);}cout << f[m] << endl;return 0; }
完全背包问题
输入样例
4 5 1 2 2 4 3 4 4 5
输出样例:
10
对于朴素做法有: 类比01背包问题
代码实现
#include <iostream>
#include <algorithm>
using namespace std;const int N = 1010;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 = 1; i <= n; i ++ )for(int j = 0; j <= m; j ++ )for(int k = 0; k * v[i] <= j; k ++ )f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);cout << f[n][m] << endl;return 0;
}
通过比较下列等式可以发现:
得到:
#include <iostream>
#include <algorithm>
using namespace std;const int N = 1010;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 = 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][j], f[i][j - v[i]] + w[i]);}cout << f[n][m] << endl;return 0;
}
一维优化
#include <iostream> #include <algorithm> using namespace std;const int N = 1010;int n, m; int v[N], w[N]; int f[N];int main() {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 ++ ){f[j] = max(f[j], f[j - v[i]] + w[i]);}cout << f[m] << endl;return 0; }
对比01背包和完全背包问题,有以下差异 :
01背包:
完全背包:
对于完全背包来说,体积的枚举可以从 v[i] 枚举到 m,因为它每 i 层的更新使用的是第 i 层的数据,不存在“数据污染”的问题。
多重背包问题
输入样例
4 5 1 2 3 2 4 1 3 4 3 4 5 2
输出样例:
10
朴素写法
#include <iostream>
#include <algorithm>
using namespace std;const int N = 110;int n, m;
int v[N], w[N], s[N];
int f[N][N];int main()
{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 <= s[i] && k * v[i] <= j; k ++ )f[i][j] = max(f[i][j], f[i - 1][j - v[i] * k] + w[i] * k);cout << f[n][m] << endl;return 0;
}
多重背包的二进制优化
众所周知,从 这 k 个2的整数次幂中选出若干个相加,可以表示出
之间的任意整数。进一步的,我们求出满足
的最大整数 p,设
那么:
- 根据 p 的最大性,有
,可推出
,因此
选出若干个相加可以表示出
之间的任意整数;
- 从
中选出若干个相加,可以表示出
之间的任何整数,而根据 Ri 的定义,
,因此,
选出若干个可以表示出
之间的任意整数。
综上所述,我们可以把数量为 的第 i 个物品拆成 p + 2个物品,他们的体积分别为:
这 p + 2 个物品可以凑成 之间所有能被Vi整除的数,并且不能凑成大于 Ci * Vi 的数。这等价于原问题中体积为 Vi 的物品可以使用 0~Ci 次。该方法仅将每种物品拆分成了
个,效率较高。
代码实现
#include <iostream>
#include <algorithm>
using namespace std;const int N = 25000, M = 2010;int n, m;
int v[N], w[N];
int f[N];int main()
{cin >> n >> m;int cnt = 0;for(int i = 1; i <= n; i ++ ){int a, b, s;cin >> a >> b >> s;int k = 1;while(k <= s){cnt ++ ;v[cnt] = a * k;w[cnt] = b * k;s -= k;k *= 2;}if(s > 0){cnt ++;v[cnt] = a * s;w[cnt] = b * s;}}n = cnt;for(int i = 1; i <= n; i ++ )for(int j = m; j >= v[i]; j -- )f[j] = max(f[j], f[j - v[i]] + w[i]);cout << f[m] << endl;return 0;
}
分组背包问题
输入样例
3 5 2 1 2 2 4 1 3 4 1 4 5
输出样例:
8
AC代码
#include <iostream>
#include <algorithm>
using namespace std;const int N = 110;int n, m;
int v[N][N], w[N][N], s[N];
int f[N];int main()
{cin >> n >> m;for(int i = 1; i <= n; i ++ ){cin >> s[i];for(int j = 0; j < s[i]; j ++ )cin >> v[i][j] >> w[i][j];}for(int i = 1; i <= n; i ++ )for(int j = m; j >= 0; j -- )for(int k = 0; k < s[i]; k ++ )if(v[i][k] <= j)f[j] = max(f[j], f[j - v[i][k]] + w[i][k]);cout << f[m] << endl;return 0;
}
【动态规划】—— 背包问题相关推荐
- 贪婪算法、递归计算、动态规划背包问题
//贪婪算法计算背包问题public static double ksack(double[] values, double[] weights, int capacity){double load ...
- 动态规划——背包问题(01背包问题)
动态规划--背包问题(01背包问题) 01背包问题(求最大价值): 问题优化 01背包问题(求方案数): 动态规划--背包问题(01背包问题) 01背包问题(求最大价值): 有N件物品和一个最多能背重 ...
- 动态规划背包问题优化空间复杂度——滚动数组
动态规划背包问题优化空间复杂度--滚动数组 背包问题 空间复杂度优化 Java代码 链接:代码随想录背包问题 背包问题 背包问题是动态规划中基本的问题,我们考虑下面的简单问题: 假设背包容量为 ...
- 动态规划——背包问题(详解)
动态规划是我最早接触的算法,一开始非常简单,固定模板题,后来愈发愈发难起来了,条件,状态压缩等等,难点主要是,状态怎么表示,状态转移方程怎么写,这篇文章将会从背包五大问题详解,希望能帮助到大家去类比, ...
- 动态规划——背包问题
动态规划--背包问题 对于背包问题,今天我们先讲解,01背包,完全背包,和多重背包.我主要从: 什么题可以用背包问题解决 背包问题的模板细节,如何准确写出背包. 1.什么题可以用背包问题解决 看到题目 ...
- 动态规划背包问题详解(二)---0-1背包问题
/** * 对于技术面试,你还在死记硬背么? * 快来"播"沙糖橘吧, * 用视频案例为你实战解读技术难点 * 聚焦Java技术疑难点,实战视频为你答疑解惑 * 越&qu ...
- 【入门级】Java解决动态规划背包问题
目录 前言 动态规划背包问题是什么? 动态规划解题转代码 第一步:拆包填表格 第二步:转为代码 一.首先看空表格:即初始化代码 二.看怎么循环填表格 三.输出结果(最大价值) 第三步:完整代码 动态规 ...
- Java-算法-动态规划-背包问题
看完本篇文章可以再多练习相似题目 算法-动态规划-背包问题-附一 一. 背包问题介绍 1. 最原始的背包问题 给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择 ...
- 动态规划---背包问题分析
0/1背包 问题描述 有N件物品和一个容量为V的背包,第i件物品的体积为c[i],价值为w[i].求将哪些物品放进背包可以使物品价值总和最大(有两种情况:不要求填满背包和填满背包). 每件商品只有一件 ...
- 动态规划 —— 背包问题 P09 —— 背包问题的变化
[输出方案] 一般而言,背包问题是要求一个最优值,如果要求输出这个最优值的方案,可以参照一般动态规划问题输出方案的方法:记录下每个状态的最优值是由状态转移方程的哪一项推出来的,换句话说,记录下它是由哪 ...
最新文章
- python启动jupyter_如何在启动JupyterNotebook时自动执行代码?
- java foreach标签,jstl c:foreach标签
- 良/恶性乳腺癌肿瘤预测
- C++ sizeof总结
- linux 文件系统原理 书,发个关于文件系统的书《Linux文件系统剖析》
- 《Go语言程序设计》读书笔记(十)反射
- 解决JS拖拽出现的问题
- 数据库学习--MySQL锁
- 《Android框架揭秘》——2.2节搭建Android平台编译环境
- 观天涯kk大神10年帖子有感
- 指纹识别技术相比于其它生物识别技术,有哪些优缺点?
- VS本地项目如何发布到服务器详细流程(IIS部署 发布网站)
- 科属种XML文档三级树状图浏览的实现
- JQuery从入门到实战
- 头歌Python实训答案——函数结构
- 内存缓存和LruCache
- 错误:App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insec
- vb html listview,VB中listview控件
- 用python动手学统计学_3-5样本统计量的性质
- C# winform PictureBox插入图片并设置自适应显示
热门文章
- 了解Oracle RAC Brain Split Resolution集群脑裂协议
- 水果店需要的设备清单有哪些,水果店都需要哪些设备
- Koch Curve
- 所有的时间伟大的好莱坞电影大片
- Python 错误:Workbook corruption: seen[2] == 4解决
- cd src make install make[1]: Entering directory `/home/xuweiliang/redis/r 错误解析
- 删除MAC系统自带的ABC输入法[亲测]
- css3中的2D和3D转换、动画效果以及布局
- 买笔记本电脑的注意事项
- oracle user does not exist,user 'scott' does not exist! 又学了一招