五大基础dp
动规条件
• 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,
即满足最优化原理。
• 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后
的过程不会影响以前的状态,只与当前状态有关。
• 有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。
(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法
相比就不具备优势)
背包dp
- 01背包 (一件物品只能选一次)
https://tg.hszxoj.com/contest/897/problem/1
点击查看代码
for(int i=1; i<=n; i++){//外层循环物品
for(int j=V; j>=v[i]; j--){//内层循环体积 倒叙循环
dp[j] = max(dp[j], dp[j-v[i]] + w[i];
}
}
- 完全背包 (不限制物品数量)
https://tg.hszxoj.com/contest/897/problem/4
点击查看代码
for(int i=1; i<=n; i++){//外层循环物品
for(int j=v[i]; j<=V; j++){//内层循环体积 顺叙循环
dp[j] = max(dp[j], dp[j-v[i]] + w[i]);
}
}
//二进制拆分
for(int i=1; i<=n; i++){
for(int k=1; k<=V/v[i]; k<<=1){
for(int j=V; j>=k*v[i]; j--){
dp[j] = max(dp[j], dp[j-k*v[i]] + k*w[i]);
}
}
}
- 多重背包 (给定物品数量)
https://tg.hszxoj.com/contest/897/problem/6
点击查看代码
//与完全背包一样使用二进制拆分
if(si > m / vi) si = m / vi;
for(int j=1; j<=si; j<<=1){
v[++cnt] = j * vi;
w[cnt] = j * wi;
si -= j;
}
if(si){
v[++cnt] = si * vi;
w[cnt] = si * wi;
}
}
n = cnt;
- 混合背包
https://tg.hszxoj.com/contest/897/problem/11
将背包都使用二进制拆分转成01包计算
- 分组背包
https://tg.hszxoj.com/contest/897/problem/13
点击查看代码
a[p][++a[p][0]] = i;//a[p][0]是每组个数
for(int p=1; p<=t; p++){
for(int j=v; j>=w[a[p][i]]; j--){
for(int i=1; i<=a[p][0]; i++){
f[j] = max(f[j], f[j-w[a[p][i]]] + c[a[p][i]]);
}
}
}
- 二维费用背包
NASA的食物计划
https://tg.hszxoj.com/contest/897/problem/12
只需要把dp数组改成二维,第一维表示质量,第二维表示卡路里即可
点击查看代码
for(int i=1; i<=n; i++){
for(int j=x; j>=v[i]; j--){
for(int a=y; a>=m[i]; a--){
f[j][a] = max(f[j][a], f[j-v[i]][a-m[i]] + k[i]);
}
}
}
线性dp
顾名思义,线性DP就是在一条线上进行DP
例如:
最长上升序列
https://tg.hszxoj.com/contest/900/problem/1
点击查看代码
for(int i=1; i<=n; i++){
dp[i] = 1;
for(int j=1; j<i; j++){
if(a[i] > a[j] and dp[i] < dp[j] + 1){
dp[i] = dp[j] + 1;
pre[i] = j;//记录前一位,方便输出
}
}
if(ans < dp[i]){
ans = dp[i];
en = i;//记录结点
}
}
//递归输出
void p(int x){
if(!x) return;
p(pre[x]);
cout << a[x] << ' ';
}
//由结点开始递归即可
拦截导弹
https://tg.hszxoj.com/contest/900/problem/3
点击查看代码
for(int i=1; i<=n; i++){
f[i] = 1;
for(int j=1; j<i; j++){
if(a[i] <= a[j]){
f[i] = max(f[i], f[j] + 1);
}
}
ans = max(ans, f[i]);
}
区间dp
这里实际上是以区间长度为阶段的,这种DP我们通常称为区间DP。
区间DP的做法较为固定,即枚举区间长度,再枚举左端点,之后枚举区间的断点进行转移。
区间类型动态规划是线性动态规划的拓展,它在分阶段划分问题时,与阶段中元素出现的顺序和由前一阶段的哪些元素合并而来有很大的关系。(例:f[i][j]=f[i][k]+f[k+1][j])
区间类动态规划的特点:
- 合并:即将两个或多个部分进行整合。
- 特征:能将问题分解成为两两合并的形式。
- 求解:对整个问题设最优值,枚举合并点,将问题分解成为左右两个部分,最后将左右两个部分的最优值进行合并得到原问题的最优值。
石子合并<3>
https://tg.hszxoj.com/contest/903/problem/3
点击查看代码
for(int i=1; i<=n*2; i++){//环状就弄成二倍串
s[i] = s[i-1] + a[i];//求前缀和
}
for(int l=2; l<=n; l++){
for(int i=1; i+l-1<=n*2; i++){
int j = i + l - 1;
g[i][j] = max(g[i+1][j], g[i][j-1]) + s[j] - s[i-1];
}
}
坐标dp
坐标型dp一般都是给定网格、序列,来求满足某种性质的最大值、最小值。f[i][j]代表以i、j结尾的满足条件的某种情况。
晴天小猪历险记之Hill
https://tg.hszxoj.com/contest/906/problem/5
点击查看代码
dp[1][1] = s[1][1];
for(int i=2; i<=n; i++){
for(int j=1; j<=i; j++){//从上到下遍历
dp[i][j] = min(dp[i-1][j], dp[i-1][j-1]) + s[i][j];
dp[i][1] = min(dp[i-1][1], dp[i-1][i-1]) + s[i][1];
dp[i][i] = min(dp[i-1][i-1], dp[i-1][1]) + s[i][i];
}
for(int j=i-1; j>=1; j--){//从右到左遍历
dp[i][j] = min(dp[i][j], dp[i][j+1] + s[i][j]);
dp[i][i] = min(dp[i][i], dp[i][1] + s[i][i]);
}
for(int j=2; j<=i; j++){//从左到右遍历
dp[i][j] = min(dp[i][j], dp[i][j-1] + s[i][j]);
dp[i][1] = min(dp[i][1], dp[i][i] + s[i][1]);
}
}
树形dp
树形DP的特殊性:没有环,dfs是不会重复,而且具有明显而又严格的层数关系。利用这一特性,我们可以很清晰地根据题目写出一个在树(型结构)上的搜索的程序。而深搜的特点,就是“不撞南墙不回头”
没有上司的舞会
https://tg.hszxoj.com/contest/909/problem/1
使用链表加边,随后dfs进行搜索
dp[x][0] 表示自己不参加 dp[x][1] 表示自己参加
点击查看代码
void dfs(int x){
for(int i=h[x]; i; i=nxt[i]){
int y = to[i];
dfs(y);
dp[x][0] += max(dp[y][1], dp[y][0]);//直接上司不参加, 则下属是否参加取较大值
dp[x][1] += dp[y][0];//直接上司参加,则下属一定不参加
}
}
初始化时注意参加即为自己的快乐值,不参加则为0
搜索时从根节点开始搜
五大基础dp的更多相关文章
- IT运维的五大基础知识
IT运维的五大基础知识 | 浏览:331 | 更新:2014-09-25 11:36 IT运维对于很多企业都很重要,接下来运维的一些基础知识天天客服IT运维总监龙少文,就给大家介绍下IT运维的基础知识 ...
- 基础dp
队友的建议,让我去学一学kuangbin的基础dp,在这里小小的整理总结一下吧. 首先我感觉自己还远远不够称为一个dp选手,一是这些题目还远不够,二是定义状态的经验不足.不过这些题目让我在一定程度上加 ...
- 基础DP(初级版)
本文主要内容为基础DP,内容来源为<算法导论>,总结不易,转载请注明出处. 后续会更新出kuanbin关于基础DP的题目...... 动态规划: 动态规划用于子问题重叠的情况,即不同的子问 ...
- hdu 5586 Sum 基础dp
Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Desc ...
- hdu 4055 Number String (基础dp)
Number String Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- 训练指南 UVA - 10917(最短路Dijkstra + 基础DP)
layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: tr ...
- 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP)
layout: post title: 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP) author: "luowentaoaa" catalog: true ...
- 「kuangbin带你飞」专题十二 基础DP
layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathj ...
- M - 基础DP
M - 基础DP Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Descriptio ...
- lightoj1004【基础DP】
从低端到顶端求个最大值: 思路: 基础DP,递推 #include<cstdio> #include<queue> #include<map> #include&l ...
随机推荐
- LyScript 实现应用层钩子扫描器
Capstone 是一个轻量级的多平台.多架构的反汇编框架,该模块支持目前所有通用操作系统,反汇编架构几乎全部支持,本篇文章将运用LyScript插件结合Capstone反汇编引擎实现一个钩子扫描器. ...
- docker中的mysql时区修改
永久修改 进入容器 docker exec -it mysql5.7 bash 查看当前时区 date -R 修改时区 cp /usr/share/zoneinfo/PRC /etc/localtim ...
- curl接口调用
CURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.最爽的是,PHP也支持 CURL 库.使用PHP的CURL 库可以简单和有效地去抓网页.你只 ...
- 探索Web API SpeechSynthesis:给你的网页增添声音
Web API SpeechSynthesis是一项强大的浏览器功能,它允许开发者将文本转换为语音,并通过浏览器播放出来.本文将深入探讨SpeechSynthesis的控制接口,包括其功能.用法和一个 ...
- Blazor OIDC 单点登录授权实例5 - 独立SSR App (net8 webapp ) 端授权
目录: OpenID 与 OAuth2 基础知识 Blazor wasm Google 登录 Blazor wasm Gitee 码云登录 Blazor OIDC 单点登录授权实例1-建立和配置IDS ...
- Ubuntu下SSH管理及SFTP下载工具Muon(Snowflake)
简介 Muon其实更像是一个基于ssh的服务器管理工具, 界面中有PAC Manager的影子, 集成了文件管理, ssh命令行, 服务器性能监测和工具包等功能. 因为这个工具的编写语言是Java, ...
- 面向对象之封装,类的相关操作,私有成员删除,构造方法__init__---day20
1.面向对象之封装 # ### 面向对象oop -封装 """ 类中封装: 成员属性 成员方法 封装等级: 1.公有:公有成员既能够在类外调用,也可在类内调用 2.私有: ...
- docker中container相关命令
1.以tomcat镜像为例运行tomcat容器(运行tomcat实例) docker run tomcat 2.宿主机端口与容器端口进行映射 -p docker run -p 8080(系统上外部端口 ...
- Kotlin 协程三 —— 数据流 Flow
目录 一.Flow 的基本使用 1.1 Sequence 与 Flow 1.2 Flow 的简单使用 1.3 创建常规 Flow 的常用方式: 1.4 Flow 是冷流(惰性的) 1.5 Flow 的 ...
- 修改centos7虚拟机的用户密码
在忘记原密码无法登录桌面的情况下,修改centos7的用户密码 非常规启动,进入编辑启动菜单 在启动GRUB菜单中选择编辑选项,按键e进入编辑; 找到linux16开头的一行,在该行中寻找ro的所在地 ...