「Note」DP 方向 - DP 优化
1. 单调队列优化 DP
1.1. 简介
当一个选手比你小还比你强,你就打不过他了。这是对单调队列简单形象的概括。
单调队列在转移的过程中不断排除不可能成为决策点的元素,使每次转移寻找决策点的时间复杂度降为 \(O(1)\)。一般地,可被单调队列优化的转移式可被写为如下形式:
\]
\]
其中需要满足 \(l_i\) 单调不降,\(A_i\) 是只与 \(i\) 有关的变量,\(B_j\) 是只与 \(j\) 有关的变量。
不难发现单调队列要维护的是 \(F_i+A_i\),每次 \(j1\) 入队时,若满足 \(F_{j1}+A_{j1}>F_{j0}+A_{j0}\) 则将 \(j0\) 弹出,直到不满足条件或者队列为空。
此时取队头元素,它一定满足在范围内最优,将其作为决策点即可。特殊地,有时需要特判队列为空的情况。
1.2. 常见技巧
大部分情况下,转移方程并不显著,因为在其中的贡献往往与 \(i,j\) 都有关,此时尝试将贡献转化为 \(A_j+B_i\) 的形式,然后在单调队列中维护 \(F_i+A_i\) 即可。
1.3. 例题
\(\color{limegreen}{P1776}\)(单调队列优化多重背包)
| \(v_i\) | \(w_i\) | \(c_i\) | \(F_{i,j}\) |
|---|---|---|---|
| 物品 \(i\) 的体积 | 物品 \(i\) 的价值 | 物品 \(i\) 的个数 | 前 \(i\) 个物品放入总体积为 \(j\) 的物品的最大价值 |
显著地,有以下转移方程:
\]
设 \(j'=j-k\times v_i\),在保证 \(i\) 不变的情况下,分别考虑每个 \(j'\) 对 \(j\) 的贡献,此时有 \(k=\frac{j-j'}{v_i}\)。此时 \(j,j'\) 在 \(\bmod v_i\) 的意义下同余,设 \(j=t\times v_i+r\) 其中 \(0\le r<v_i\),考虑将贡献拆分有 \(j'=j-k\times v_i,k=\left\lfloor\frac{j}{v_i}\right\rfloor-\left\lfloor\frac{j'}{v_i}\right\rfloor=t-\left\lfloor\frac{j'}{v_i}\right\rfloor\),将原方程改写:
\]
不难想到在枚举 \(r\) 的基础上,枚举 \(j\) 进行单调队列优化。
$\text{Code}$:
#define LL long long
#define UN unsigned
#include<bits/stdc++.h>
using namespace std;
//--------------------//
const int N=1e5+1;
int n,V;
int v[N],w[N],c[N];
int ans,f[N];
int head,tail;
int q[N][2];
//--------------------//
int main()
{
scanf("%d%d",&n,&V);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&w[i],&v[i],&c[i]);
for(int i=1;i<=n;i++)
for(int r=0;r<v[i];r++)
{
head=tail=1;
q[1][0]=r,q[1][1]=f[r];
for(int tem,t,j=r+v[i];j<=V;j+=v[i])
{
tem=f[j]-j/v[i]*w[i],t=j/v[i];
while(head<=tail&&q[head][0]<j-c[i]*v[i])
head++;
f[j]=max(f[j],q[head][1]+t*w[i]);
while(head<=tail&&q[tail][1]<tem)
tail--;
q[++tail][0]=j,q[tail][1]=tem;
}
}
for(int i=1;i<=V;i++)
ans=max(ans,f[i]);
printf("%d",ans);
return 0;
}
\(\color{royalblue}{P3089}\)
| \(x_i\) | \(p_i\) | \(F_{i,j}\) | \(now_i\) |
|---|---|---|---|
| 目标点 \(i\) 的坐标 | 目标点 \(i\) 的分数 | 跳至目标点 \(i\),上一个目标点是 \(j\) ,所能获得的最大分数 | 当前单调队列还未加入的最近位置 |
先考虑单方向的做法,显著地,按照 \(x_i\) 排序后有以下转移方程:
\]
我们发现当 \(i\) 固定时并不能直接用单调队列优化,因为维护的 \(\max\) 中存在两个不固定值 \(j,k\)。考虑固定 \(j\),当 \(i\) 上升时,\(k\) 的范围单调不减,此时可以用单调队列维护。
对于每一个 \(j\) 维护一个单调队列,用 \(now_j\) 记录还未进队的最近位置,每次枚举 \(i\) 时,将符合条件的 \(k\) 入队,并更新 \(now_j\)。
至于向另一方向跳的情况,将数轴左右翻转再做一遍 DP 即可。
\(\color{royalblue}{P4544}\)
| \(ka\) | \(e\) | \(x_i\) | \(c_i\) | \(v_i\) | \(f_{i,j}\) |
|---|---|---|---|---|---|
| 需要饲料总数 | 中点坐标 | 商店 \(i\) 坐标 | 商店 \(i\) 库存 | 商店 \(i\) 价格 | 走到商店 \(i\) 经过交易后得到 \(j\) 个饲料的最小消费 |
先按照 \(x_i\) 排序,显著地,转移方程:
\]
将其转化:
\]
显著的单调队列。其中需要注意的是初值的设置以及转移的始末位置。
x. 前置知识 决策单调性
x.1. 简介
决策单调性是一个优秀的性质,对于具有决策单调性的动态规划可以采用很多方法进行优化。
通常地,决策单调性体现在 1D 维度上。当 \(j<j'<i<i'\) 时,若 \(F_i\) 从 \(F_{j'}\) 转移过来,那么 \(F_i'\) 不可能从 \(F_j\) 转移过来,只可能从 \(F_j'\) 或之后的状态转移。这种性质可称之为决策单调性。
x.2. 四边形不等式
四边形不等式如下,在 \(a<b<c<d\) 的情况下 \(w(a,d)+w(b,c)>w(a,c)+w(b,d)\)。
设 \(F_i\) 由 \(F_j+w(i,j)\) 转移来,若满足四边形不等式则称其具有决策单调性。
证明略,待施工。
2. 斜率优化
2.1. 简介
当一个最优化 DP 的转移方程形如:
\]
\]
即其中有一些只关于 \(i,j\) 其中一个的项和一个关于 \(i,j\) 两个变量的项,可以考虑用斜率优化来解决。
先对原式进行化简。设 \(F_i\) 由 \(F_j\) 转移过来,有 \(F_i=F_j+A_i+B_j+a_i\times b_j\),移项得:
\]
设 \(y=F_j+B_j,x=b_j,k=a_i,b=A_i-F_i\),当 \(i\) 固定时,我们得到了一个 \(k\) 固定的一次函数,使其经过不同的 \((x,y)\)(与 \(j\) 有关),可以得到不同的截距 \(b\)(与 \(F_i\) 有关),其中取截距最大或最小,可以得到 \(F_i\) 的最大或最小值,因题而异。
具体地,我们维护一个凸包,取一次函数与切点为决策点。
2.2. 常见技巧
「Note」DP 方向 - DP 优化的更多相关文章
- LG3205/BZOJ1996 「HNOI2010」合唱队 区间DP
区间DP 区间DP: 显然是一个区间向左右拓展形成的下一个区间,具有包含关系,所以可以使用区间DP. 状态设计: 考虑和关路灯一样设计状态 因为不知道当前这个区间是从哪个区间拓展而来,即不知道这个区间 ...
- LOJ 6435 「PKUSC2018」星际穿越——DP+倍增 / 思路+主席树
题目:https://loj.ac/problem/6435 题解:https://www.cnblogs.com/HocRiser/p/9166459.html 自己要怎样才能想到怎么做呢…… dp ...
- loj#2483. 「CEOI2017」Building Bridges 斜率优化 cdq分治
loj#2483. 「CEOI2017」Building Bridges 链接 https://loj.ac/problem/2483 思路 \[f[i]=f[j]+(h[i]-h[j])^2+(su ...
- loj#2002. 「SDOI2017」序列计数(dp 矩阵乘法)
题意 题目链接 Sol 质数的限制并没有什么卵用,直接容斥一下:答案 = 忽略质数总的方案 - 没有质数的方案 那么直接dp,设\(f[i][j]\)表示到第i个位置,当前和为j的方案数 \(f[i ...
- 「洛谷5017」「NOIP2018」摆渡车【DP,经典好题】
前言 在考场被这个题搞自闭了,那个时候自己是真的太菜了.qwq 现在水平稍微高了一点,就过来切一下这一道\(DP\)经典好题. 附加一个题目链接:[洛谷] 正文 虽然题目非常的简短,但是解法有很多. ...
- LOJ3058. 「HNOI2019」白兔之舞 [DP,MTT]
LOJ 前置知识:任意长度NTT 普通NTT只能做\(2^k\)的循环卷积,尝试扩展成长度为\(n\)的循环卷积,保证模意义下\(\omega_n\)存在. 不管怎样还是要算点值.推式子: \[ \b ...
- LOJ 2304 「NOI2017」泳池——思路+DP+常系数线性齐次递推
题目:https://loj.ac/problem/2304 看了各种题解…… \( dp[i][j] \) 表示有 i 列.第 j 行及以下默认合法,第 j+1 行至少有一个非法格子的概率,满足最大 ...
- 逛公园「NOIP2017」最短路+DP
大家好我叫蒟蒻,这是我的第一篇信竞题解blog [题目描述] 策策同学特别喜欢逛公园. 公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边.其中 \(1\) 号点是公园 ...
- BZOJ1369/LG4395 「BOI2003」Gem 树形DP
问题描述 LG4395 BZOJ1369 题解 发现对于结点 \(x\) ,其父亲,自己,和所有的孩子权值不同,共 \(3\) 类,从贪心的角度考虑,肯定是填 \(1,2,3\) 这三种. 于是套路树 ...
- 「题解」:[组合数学][DP]:地精部落
拿到这道题秒懂题意:波动序列. 然鹅不会打.想了一节课,想打纯组合数学,结果找不到规律. 想的是先假设拍出一个序列,然后交换其中的元素求组合, 无奈没啥规律可循,显然不能一口气求出来(我说的是我没办法 ...
随机推荐
- 带大家做了个 AI 项目,没想到这么简单!
大家好,我是程序员鱼皮,现在已经是全民 AI 时代了,咱们程序员更要想办法榨干 AI,把 AI 利用起来.前几天我一时兴起,直播用 2 多个小时的时间,从需求分析开始,带大家做了一个 AI 海龟汤游戏 ...
- 【技术分析】简单了解 AccessControl
当我们开发一个智能合约,但是里面有一些函数不能随便让别人调用,只能"拥有权限"的管理员能够调用,那么这时候我们会用到权限管理机制. 实现起来也很简单,设置一个 owner 变量,通 ...
- 【Python】Python使用Tk实现动态爱心效果
[Python]Python使用Tk实现动态爱心效果 深夜种下希望,梦中便能发芽 相对于之前的版本(晚上星月争辉,美梦陪你入睡),解决了看起来很卡.爱心跳动死板和外围光环不怎么灵动的问题,添加了文字功 ...
- Quartz.NET - 教程 2: 作业和触发器
译者注: 目录在这 Quartz.NET 3.x 教程 原文在这 Lesson 2: Jobs And Triggers Quartz API Quartz API 的主要接口和类如下: ISched ...
- restful 服务器一个问题,看ChatGPT的威力
看看是否牛逼: 真不是写代码的料,也没有这样的天赋,仅仅玩玩而已. 问题:客户端边缘路由中一段js代码,使用get请求一个方法,把json数据送入数据库相关表.由于种种原因导致长连接,通过资源管理器可 ...
- study PostgreSQL【2-FireDAC连接PostgreSQL】
就这么个简单问题,一下午时间.想想就憋屈. 那么牛逼哄哄FireDAC居然连接PostgreSQL出问题了.帮助中说的啥意思,咱也不明白.网上一通也是云里雾里. 上干货,具体点: TFDConnect ...
- 一个Bug让人类科技倒退几十年?
大家好,我是良许. 前几天在直播的时候,问了直播间的小伙伴有没人知道「千年虫」这种神奇的「生物」的,居然没有一人能够答得上来的. 所以,今天就跟大家科普一下这个人类历史上最大的 Bug . 1. 全世 ...
- 请求参数的绑定(获取请求数据)、请求参数是一个POJO
一. @Controller @RequestMapping("/parem") public class ParamController { /** * springmvc接受请 ...
- java——文件的上传、下载、删除操作DEMO
记录一下java实现文件的上传.下载.删除的功能demo: /** * Controller */ @Slf4j @RestController @RequestMapping public clas ...
- 康谋分享 | aiSim5仿真场景重建感知置信度评估(三)
aiSim5重建高精度的真实交通场景,用于测试和训练ADAS/AD系统.内置场景包括赛道.车库.高速公路和城市环境.通过全局行动日志,aiSim能将驾驶数据转化为场景重建.车道线检测算法在仿真与现实世 ...