动态规划是我最早接触的算法,一开始非常简单,固定模板题,后来愈发愈发难起来了,条件,状态压缩等等,难点主要是,状态怎么表示,状态转移方程怎么写,这篇文章将会从背包五大问题详解,希望能帮助到大家去类比,思考其他动态规划题目。


首先先来看看动态规划的定义
动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

看完定义我们开始应用了!来看基本的01背包问题,也是最经典的动态规划01背包问题(点此跳转题目,下同)
[ps:建议而外开个网页去打开题目链接,用Ctrl+tab食用更佳]

这题所求的是V容积下能够装的物品的最大值。很显然有容积的限制有时候你不能全部都装,又有体积和价值的不确定性,可能你选小体积的反而会有更大的价值,如果去暴力枚举时间复杂度呈指数显然不能ac,那么就需要六大算法之一动态规划了。

明确的一点此题是求最大值,而每个物品至多选一次,也就是只有选和不选俩个状态。我们可以一个一个物品去决策这个物品是该选还是不该选,这只需要一个max函数就能完成了。现在的问题是如何去定义,怎么去记录这个决策过程。依靠现有的知识能储存多组数据的只有数组了,我们可以先定义一个二维数组dp[N][N]去记录这个过程。

int dp[N][N]; //dp[i][j]表示容积为j的背包只装前i个物品可以达到的最大价值

这也是动态规划的第一步,明确数组的含义或者集合的含义。

接下来可以一个一个去决策了,先预知一下,肯定需要一个for循环去枚举物品,枚举完物品又需要一个for循环去枚举体积。在选或不选的情况下去择优,更新dp[i][j],n2的时间复杂度,显然对付这题很容易了。

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-1][j-v[i]]+w[i]);  //只有物品体积大于背包容积了才可以开始决策择优选或不选。}
}

那么最终答案就是dp[n][m],在只考虑前n个物品最大容积为m的背包可以装的物品的最大价值ac代码:

#include <iostream>using namespace std;const int N = 1010;int n, m;
int v[N], w[N];
int dp[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++) {dp[i][j] = dp[i-1][j];if(j>=v[i]) dp[i][j] = max(dp[i][j], dp[i-1][j-v[i]]+w[i]);}}cout << dp[n][m] << endl;return 0;
}

可能有人了解到可以空间压缩,滚动数组等等,在此先不讲,我们前面先讲思维。(有兴趣的我后面可能有浅讲一手,你们可以浅看一手)
好回归正题,我们来总结一下01背包问题。
首先是一个状态表示二维数组dp[][],其次就是状态计算,怎么得到这个dp[i][j],其实也挺简单,刚入门就是这么简单。

(建议消化一下,新知识的接纳需要沉淀)

好我们开始下一个 完全背包问题

与01背包不同 的 是,此问题的物品可以选择无限个;
状态表示跟01背包如出一辙,你问为什么,这么类似的题你不用类似的状态表示么,你还能想出其他的么,想出了当我没说

而状态计算跟刚刚也一样么,不错,一样的地方是一模一样的,只需要再添一重循环去循化个数就好了。这也是动态规划题目经常会遇到的设定,会给出体积限制,数量限制等等限制。代码如下

#include<iostream>using namespace std;const int N = 1010;int dp[N][N];
int v[N],w[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++) {for(int k = 0 ; k*v[i]<=j ; k++)dp[i][j] = max(dp[i][j],dp[i-1][j-k*v[i]]+k*w[i]);}}cout<<dp[n][m]<<endl;
}

欸,复制过去为什么没ac,哈哈显然对于这道题n3的时间复杂度就tle了,这里先不说ac代码了,如果你仔细看完我对01背包的描述,这上面的代码应该是一边过,模拟一下代码就好了,很清晰。

接下来是 多重背包问题

与上述俩个问题不同的是既不是只能选一个也不是无限选,多重背包问题中是每个物品有数量限制,只能选几个。
这就是数量限制了,加嘛,加条件而已,谁都会。

#include <iostream>using namespace std;int dp[105][105];
int v[105],w[105],s[105];int main(){int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d%d%d",&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++){if(j>=k*v[i]){dp[i][j]=max(dp[i][j],dp[i-1][j-k*v[i]]+k*w[i]);}}}}printf("%d",dp[n][m]);return 0;
}

欸,为什么这题n3方的时间复杂度既然过了,因为这题数值范围比较小的说(不然你能过??)

三题下来貌似很简单嘛,就很模板化了,接下来继续看 分组背包问题

此题与上述三题又有点不一样了。他将所有物品分成几个组,欸每组只能选几个。他不关心你每个能取几个了,他关心你每组能取几个了。emm稍有变通一下,我们刚刚关心每个第一重循环就去枚举物品个数,那我们现在关系每组,就只需要第一组去枚举组数就好了。

#include <iostream>
using namespace std;const int N=110;
int dp[N][N];  //只从前i组物品中选,当前体积小于等于j的最大值
int v[N][N],w[N][N],s[N];   //v为体积,w为价值,s代表第i组物品的个数
int n,m,k;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=0;j<=m;j++){dp[i][j]=dp[i-1][j];  //不选for(int k=0;k<s[i];k++){if(j>=v[i][k])  dp[i][j]=max(dp[i][j],dp[i-1][j-v[i][k]]+w[i][k]);  }}}cout<<dp[n][m]<<endl;
}

最后最后就是混合背包问题了,顾名思义,将上述背包混合起来,有的关心个数,有的关心组数,有的有条件限制,有的有数量限制,请听题 混合背包问题

如果你会了这题,那么证明你不是小白了,因为二维很难做,在此先不贴ac代码了。
好我们认识了这么多的背包问题,也算是动态规划入门了,现在你应该也对动态规划有所了解了,总比贪心好做吧!我们来归纳一下基础的动态规划题。


根据闫氏DP分析法,总的包括俩部分
一部分是状态表示:也就是你需要去找一个集合去不重不漏的把所有情况涵盖在内,之后是解释这个集合的属性,可能是最大值,最小值,也可能是数量,直观感受就是去描述你这个数组代表着什么;
另一部分就是去状态计算:去写状态转移方程,直观的就是去想你当前这个单元是有哪几部分构成,如何去决策择优。例如01背包问题,dp[i][j]里面由dp[i-1][j]和dp[i-1][j-v[i]]+w[i]俩部分构成。咳咳肯定有小伙伴懵逼,我来翻译一下。就是说在容积为j的背包只挑前i个物品的最大价值可能是在容积为j的背包只挑前i-1个物品的最大价值,也可能是在容积为j-v[i]的背包只挑前i-1个物品的最大价值(第i个已经挑了)有没有顿悟了(没有在返回几行再看一遍/头槌)。至此动态规划--背包问题入门思维版已经结束了,相信你对背包问题已经了解了,慢慢感受状态表示和状态计算的魅力吧。

动态规划——背包问题(详解)相关推荐

  1. 动态规划背包问题详解(二)---0-1背包问题

    /**  * 对于技术面试,你还在死记硬背么?  * 快来"播"沙糖橘吧,  * 用视频案例为你实战解读技术难点  * 聚焦Java技术疑难点,实战视频为你答疑解惑  * 越&qu ...

  2. 动态规划------背包问题详解

    文章目录 一.01背包 二.完全背包 三.多重背包 四.二维费用背包 一.01背包 有n件物品,每件物品占用的空间为w[i], 价值为p[i]. 有容量为 V 的背包.求在容量允许的范围下,背包装入物 ...

  3. c语言背包问题装字母,C语言动态规划之背包问题详解

    01背包问题 给定n种物品,和一个容量为C的背包,物品i的重量是w[i],其价值为v[i].问如何选择装入背包的物品,使得装入背包中的总价值最大?(面对每个武平,只能有选择拿取或者不拿两种选择,不能选 ...

  4. (转)dp动态规划分类详解

    dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间 ...

  5. 01背包问题详解(浅显易懂)

    01背包问题详解 01背包是一种动态规划问题.动态规划的核心就是状态转移方程,本文主要解释01背包状态转移方程的原理. 问题描述 01背包问题可描述为如下问题: 有一个容量为V的背包,还有n个物体.现 ...

  6. 五大算法之动态规划套路详解(1)

    前言: 一.Why?为什么需要动态规划 二.What?什么是动态规划 三.How?如何利用动态规划做题 四.思路总结 前言: 对于很多学习算法的同学来说,往往是跟着老师和学校教材上课,然后去刷题练熟练 ...

  7. 最长公共子序列 - 北京大学郭炜 动态规划代码详解

    最长公共子序列 - 北京大学郭炜 动态规划代码详解 解题思路: 该题可用动态规划解决.动态规划需要我们找出子问题. 假设我们输入两个字符串: ACTTGACC CGTT 那么如何通过动态规划算出其最大 ...

  8. 背包问题详解-动态规划

    目录 01背包问题 暴力法 空间优化 背包问题的所有情况 完全背包问题 状态转移方程分析 空间优化 方法二:记录第i件物品的数据k 方法三:转换成01背包 多重背包 方法一:记录第i件物品的数据k 方 ...

  9. 0-1背包问题详解(一步一步超详细)

    1.什么叫01背包问题? 背包问题通俗的说,就是假如你面前有5块宝石分别为a, b, c, d, e,每块宝石的重量不同,并且每块宝石所带来的价值也不同(注意:这里宝石的重量的价值没有特定关系),目前 ...

  10. 九种 0-1 背包问题详解

    目录 动态规划概念 问题1:0-1背包问题 问题2:完全背包问题 问题3:多重背包问题 问题4:混合背包问题 问题5:二维背包问题 问题6:分组背包问题 问题7:有依赖的背包问题 (困难) 问题8:背 ...

最新文章

  1. 美国卡尔顿学院计算机专业怎么样,美国卡尔顿学院排名
  2. c语言节点导入数据编程,编程小白。用C语言计算SR E2E ARQ模式下节点的数据分析...
  3. Objective-C中一种消息处理方法performSelector: withObject:
  4. 将应用打包为 Snaps
  5. 分计算iv值_一文读懂评分卡的IV、KS、AUC、GINI指标
  6. linux grep -11,11个高级Linux字符类和括号表达式的grep命令
  7. 使用JSON Viewer直观查看JSON数据
  8. VCL组件之公用对话框组件
  9. 关于mysql叙述中错误的是什么_以下关于MySQL的叙述中,错误的是( )。_学小易找答案...
  10. ansible安全之加密主机清单
  11. java 网络百度搜索_Java爬虫怎么调用百度搜索引擎,对关键字的网页爬取?
  12. mapgis67安装输入计算机名称,mapgis67_dogserver67.exe_mapgis67安装教程
  13. python网络爬虫课程设计报告摘要_课程设计 Python 网络爬虫(广度优先方法)
  14. Mapped Statements collection already contains value for xxx
  15. 重置CAD 或者Civil 3d的所有环境
  16. HTML-day02会员登录案例
  17. angular如何生成条形码下载条形码
  18. 关于判别分析的学习-距离判别法
  19. 炒菜机器人“精确”破题中餐标准化
  20. python可视化库matplotlib_Python可视化库matplotlib(基础整理)

热门文章

  1. 考勤名单node统计
  2. 查询结果按照数量排序,并且将某条记录固定放到最后一行
  3. 这人写得有意思,呵呵:老婆的爆笑日记
  4. 申请泛域名证书和自动续签(网站证书https)
  5. pyecharts-地图
  6. 夸克APP端智能:文档关键点检测实践与应用
  7. 装完系统安装完驱动后重启进入系统蓝屏0X000000A5
  8. UE4上传图片到服务器
  9. halcon灰度积分投影/垂直积分投影
  10. 用幻灯片做“一站到底”的抢答器