五大基础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 ...
随机推荐
- C/C++ 静态编译SQLITE数据库API
C/C++ 编译并使用Sqlite数据库,实现增删改查. 首先下载数据库: https://sqlite.org/download.html 分别下载:sqlite-amalgamation-3350 ...
- 协程(Python)
一.gevent #__author__:Kelvin #date:2020/5/13 13:34 from gevent import monkey monkey.patch_all() impor ...
- 使用C语言构建一个独立栈协程和共享栈协程的任务调度系统
使用了标准库头文件 <setjmp.h>中的 setjmp 和 longjmp两个函数,构建了一个简单的查询式协作多任务系统,支持独立栈和共享栈两种任务. 其中涉及到获取和设置栈的地址操作 ...
- Linux-双网卡绑定bond详解
1.什么是bond 网卡bond是通过多张物理网卡绑定为一个逻辑网卡,实现本地网卡的冗余,带宽扩容和负载均衡,在生产场景中是一种常用的技术.Kernels 2.4.12及以后的版本均供bonding模 ...
- 使用VNC在Windows上远程访问Ubuntu服务器
Step 0:事前准备 一台安装了ghome桌面的Ubuntu服务器(用作server) 一台Windows机器(用作client) Step 1:Linux服务器 在Ubuntu上安装一个VNC服务 ...
- 【JS】一个思路搞定三道Promise并发编程题,手摸手教你实现一个Promise限制器
壹 ❀ 引 之前在整理手写Promise相关资料时,在文章推荐区碰巧看到了一道手写Promise并发控制调度器的笔试题(大厂可能爱考),结果今天同事又正好问了我一个关于Promise调度处理的场景问题 ...
- Python中保存字典类型数据到文件
三种方法: 1.在 Python 中使用 pickle 模块的 dump 函数将字典保存到文件中import pickle my_dict = { 'Apple': 4, 'Banana': 2, ' ...
- Python subProcess库以及Popen类的使用
subprocess库是一个十分强大且常用的库,它可以用来调用第三方工具(例如:exe.另一个python文件.命令行工具). 1.常用函数call() :执行由参数提供的命令,把数组作为参数运行命令 ...
- Gerrit 笔记
Gerrit 通过git push后增加一个中间状态, 来完成代码审批环节, 因此在git commit的时候增加了一个change id, 并且push到定制的target, 在push之后, 需要 ...
- 【Unity3D】UGUI之Button
1 Button属性面板 在 Hierarchy 窗口右键,选择 UI 列表里的 Button 控件,即可创建 Button 控件,选中创建的 Button 控件,按键盘[T]键,可以调整 But ...