背包问题学习笔记 / Dynamic Programming(updating)
01背包问题
朴素版:(二维数组)
状态表示: dp[i][j]:从前i个物品中选择(每个物品只能选0或1个)且总体积不超过j的集合的最大价值,则dp[n][m]就是最终答案(n:物品数量,m:最大体积)
状态计算: dp[i][j] = max ( dp[i-1][j] , dp[i-1][j-vi]+wi ) // 由含i和不含i两个子集合计算而来(vi:物品体积,wi:物品价值)
核心代码:
int n, m; // n:物品数量, m:最大体积
int v[N], w[N], dp[N][M]; void keyCode()
{
for(int i = 1; i <= n; i++)
for(int j = 0; j <= m; j++)
{
dp[i][j] = dp[i-1][j];
if(v[i] >= j) dp[i][j] = max(dp[i][j], dp[i-1][j-v[i]] + w[i]);
}
}
空间优化版:(滚动数组,二维数组优化至一维)
状态表示:dp[j]:在外循环的第i层时,表示从前i个物品中选择(每个物品只能选0或1个)且总体积不超过j的集合的最大价值,n层循环后,dp[m]就是最终答案
状态计算:dp[j] = max ( dp[j] , dp[j-vi]+wi ) // 由含i和不含i两个子集合计算而来
核心代码:
int n, m; // n:物品数量, m:最大体积
int v[N], w[N], dp[N]; void keyCode()
{
for(int i = 1; i <= n; i++)
// 反向遍历, 否则dp[j-v[i]]可能为dp[i][j-v[i]](用更新后的值来更新导致出错)
for(int j = m; j >= v[i]; j--)
dp[j] = max(dp[j], dp[j-v[i]] + w[i]); }
完全背包问题
朴素版:(二维数组)
状态表示:dp[i][j]:从前i种物品中选择(每种物品可以任选个数)且总体积不超过j的集合的最大价值,则dp[n][m]就是最终答案
状态计算:dp[i][j] = max ( dp[i-1][j] , dp[i][j-vi]+wi )
证明:dp[i][j] = max ( dp[i-1][j] , dp[i-1][j-vi]+wi , dp[i-1][j-2vi]+2wi , dp[i-1][j-3vi]+3wi , ...... )
dp[i][j-vi] = max ( dp[i-1][j-vi] , dp[i-1][j-2vi]+wi , dp[i-1][j-3vi]+2wi , ...... )
Thus,dp[i][j-vi]+wi = max ( dp[i-1][j-vi]+wi , dp[i-1][j-2vi]+2wi , dp[i-1][j-3vi]+3wi , ...... )
Thus,dp[i][j] = max ( dp[i-1][j] , dp[i][j-vi]+wi )
核心代码:
int n, m; // n:物品数量, m:最大体积
int v[N], w[N], dp[N][M]; void keyCode()
{
for(int i = 1; i <= n; i++)
for(int j = 0; j <= m; j++)
{
dp[i][j] = dp[i-1][j];
if(j >= v[i]) dp[i][j] = max(dp[i][j], dp[i][j-v[i]] + w[i]);
}
}
空间优化版:(滚动数组,二维数组优化至一维)
状态表示:dp[j]:在外循环的第i层时,表示从前i种物品中选择(每种物品可以任选个数)且总体积不超过j的集合的最大价值,n层循环后,dp[m]就是最终答案
状态计算:dp[j] = max ( dp[j] , dp[j-vi]+wi ) // 由含i和不含i两个子集合计算而来
核心代码:
int n, m; // n:物品数量, m:最大体积
int v[N], w[N], dp[N]; void keyCode()
{
for(int i = 1; i <= n; i++)
// 正向遍历, 使得dp[j-v[i]]为dp[i][j-v[i]]
for(int j = v[i]; j <= m; j++)
dp[j] = max(dp[j], dp[j-v[i]] + w[i]); }
多重背包问题
朴素版:(二维数组+三重循环)
状态表示:dp[i][j]:从前i种物品中选择(每种物品最多选择si个)且总体积不超过j的集合的最大价值,则dp[n][m]就是最终答案
状态计算:dp[i][j] = max ( dp[i-1][j],dp[i-1][j-v]+w,dp[i-1][j-2v]+2w,...,dp[i-1][j-sv]+sw )
核心代码:
int n, m; // n:物品数量, m:最大体积
int v[N], w[N], s[S];
int dp[N][M]; void keyCode()
{
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++)
dp[i][j] = max(dp[i][j], dp[i-1][j-k*v[i]] + k*w[i]);
}
优化版:(一维数组+二重循环)
二进制优化:对于每种物品,将其按2的次幂大小拆分合并,如s[i]=12时,方案为:第1个物品合并,第2~3个物品合并,第4~7个物品合并,第8~12个物品合并(1,2,4,5)。这样,就将多重背包问题转化成01背包问题
状态表示:dp[j]:在外循环的第i层时,表示从前i个物品中选择(每个物品只能选0或1个)且总体积不超过j的集合的最大价值,n层循环后(n为问题转化后的新n),dp[m]就是最终答案
状态计算:dp[j] = max ( dp[j] , dp[j-vi]+wi )
核心代码:
int n, m;
int v[N], w[N], dp[M]; // N:maxn * logmaxs void keyCode()
{
int cnt = 0;
for(int i = 1; i <= n; i++)
{
int a, b, s; // vi, wi, si
cin >> a >> b >> s;
int p = 1;
while(p <= s)
{
cnt ++;
v[cnt] = a * p, w[cnt] = b * p;
s -= p, p *= 2;
}
if(s > 0)
{
cnt ++;
v[cnt] = a * s, w[cnt] = b * s;
}
}
n = cnt; // n --> 问题转化后的新n
for(int i = 1; i <= n; i++)
for(int j = m; j >= v[i]; j--) // 反向遍历
dp[j] = max(dp[j], dp[j-v[i]] + w[i]);
}
分组背包问题
朴素版:(二维数组)
状态表示:dp[i][j]:从前i组物品中选择(每组物品中只能选择0或1个)且总体积不超过j的集合的最大价值,则dp[n][m]就是最终答案
状态计算:dp[i][j] = max ( dp[i-1][j],dp[i-1][j-vi,1]+wi,1,dp[i-1][j-vi,2]+wi,2,dp[i-1][j-vi,3]+wi,3,... )
核心代码:
int n, m; // n:物品数量, m:最大体积
int s[N], v[N][S], w[N][S];
int dp[N][M]; void keyCode()
{
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= m; j++)
{
dp[i][j] = dp[i-1][j];
for(int k = 1; k <= s[i]; k++)
if(v[i][k] <= j)
dp[i][j] = max(dp[i][j], dp[i-1][j-v[i][k]] + w[i][k]);
}
}
}
空间优化版:(滚动数组,二维数组优化至一维)
int n, m; // n:物品数量, m:最大体积
int s[N], v[N][S], w[N][S];
int dp[M]; void keyCode()
{
for(int i = 1; i <= n; i++)
{
for(int j = m; j >= 0; j--) // 反向遍历
{
for(int k = 1; k <= s[i]; k++)
if(v[i][k] <= j)
dp[j] = max(dp[j], dp[j-v[i][k]] + w[i][k]);
}
}
}
背包问题学习笔记 / Dynamic Programming(updating)的更多相关文章
- angular2 学习笔记 ( Dynamic Component 动态组件)
更新 2018-02-07 详细讲一下 TemplateRef 和 ViewContainerRef 的插入 refer : https://segmentfault.com/a/1190000008 ...
- DP背包问题学习笔记及系列练习题
01 背包: 01背包:在M件物品中取出若干件物品放到背包中,每件物品对应的体积v1,v2,v3,....对应的价值为w1,w2,w3,,,,,每件物品最多拿一件. 和很多DP题一样,对于每一个物品, ...
- 动态规划 Dynamic Programming 学习笔记
文章以 CC-BY-SA 方式共享,此说明高于本站内其他说明. 本文尚未完工,但内容足够丰富,故提前发布. 内容包含大量 \(\LaTeX\) 公式,渲染可能需要一些时间,请耐心等待渲染(约 5s). ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图 代码工程地址: https://github.c ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader)
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader) 代码工程 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二)
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二) 代码工程地址: https:/ ...
- Dynamic CRM 2013学习笔记 系列汇总
这里列出所有 Dynamic CRM 2013学习笔记 系列文章,方便大家查阅.有任何建议.意见.需要,欢迎大家提交评论一起讨论. 本文原文地址: Dynamic CRM 2013学习笔记 系列汇总 ...
- IOS学习笔记之关键词@dynamic
IOS学习笔记之关键词@dynamic @dynamic这个关键词,通常是用不到的. 它与@synthesize的区别在于: 使用@synthesize编译器会确实的产生getter和setter方法 ...
- Dynamic CRM 2013学习笔记(一)插件输入实体参数解析
1. 问题描述 最近新建了一个post事件的插件,传入的参数处理如下: 1: if (context.InputParameters.Contains("Target") &a ...
随机推荐
- SpringBoot如何优雅关闭(SpringBoot2.3&Spring Boot2.2)
SpringBoot如何优雅关闭(SpringBoot2.3&Spring Boot2.2) 优雅停止&暴力停止 暴力停止:像日常开发过程中,测试区或者本地开发时,我们并不会考虑项目关 ...
- CSS加载不会阻塞DOM树解析
1.css的加载不会阻塞DOM树解析. 1).css加载不会阻塞DOM树的解析: 2).css加载会阻塞DOM树渲染: 先把DOM树结构先解析完,等CSS加载完后根据最终样式渲染DOM树,免了css加 ...
- ELF文件结构
ELF文件结构 ELF文件的全称是Executable and Linkable Format,直译为"可执行可链接格式",包括目标文件(.o).可执行文件(可以直接运行).静态链 ...
- 百万数据 mysql count(*)优化
一.故事背景有一张 500w 左右的表做 select count(*) 速度特别慢. 二.原 SQL 分析Server version: 5.7.24-log MySQL Community Ser ...
- 图文详解 HDFS 的工作机制及其原理
大家好,我是大D. 今天开始给大家分享关于大数据入门技术栈--Hadoop的学习内容. 初识 Hadoop 为了解决大数据中海量数据的存储与计算问题,Hadoop 提供了一套分布式系统基础架构,核心内 ...
- Android7.1.2 源码编译并烧写Nexus5X
1.环境配置 Ubuntu18.04 openJDK1.8 Python2.7 2.更新Ubuntu镜像源 编辑/etc/apt/source.list,替换为以下内容 deb http://mirr ...
- 面试官:Dubbo是什么,他有什么特性?
哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 书接上回,今天还是过周末,虽然 ...
- DataX异构数据源离线同步工具json文件配置说明
DataX 是阿里开源的一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL.Oracle等).HDFS.Hive.ODPS.HBase.FTP等各种异构数据源之间稳定高效的数据同步功能 ...
- Servlet的本质
简介:Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层. 功能:使 ...
- (干货)基于 veImageX 搭建海报生成平台 -- 附源码
前言 618 年中促销即将来临,很多公司都会通过海报来宣传自己的促销方案,通常情况下海报由设计团队基于 PS.Sketch 等工具创作,后期若想替换海报文案.商品列表等内容则需打开原工程进行二次创作, ...