DP斜率优化总结
DP斜率优化总结
任务安排1
首先引入一道题,先\(O(N^2)\)做法:分别预处理出\(T_i,C_i\)前缀和\(t[i],c[i]\),设\(f[i]\),其中\(f[i]\)并不表示前\(i\)个任务花费的时间,而是壳含前面所有决策对于后面的影响。这道题dp思路就是边决策边加上当前决策对于后面的影响(一种“费用提前计算”的思想)
转移方程:
\]
#include <cstdio>
#include <cstring>
#define MIN(A,B) ((A)<(B)?(A):(B))
#define MAXN 5005
using namespace std;
int f[MAXN];
int sumt[MAXN],sumc[MAXN];
int n,s;
int main(){
memset(f, 0x3f, sizeof(f));
f[0]=0;
scanf("%d\n%d", &n, &s);
for(int i=1;i<=n;++i){
int t,c;
scanf("%d %d", &t, &c);
sumt[i]=sumt[i-1]+t;
sumc[i]=sumc[i-1]+c;
}
for(int i=1;i<=n;++i)
for(int j=0;j<i;++j){
f[i]=MIN(f[j]+(sumc[i]-sumc[j])*sumt[i]+s*(sumc[n]-sumc[j]), f[i]);
}
printf("%d", f[n]);
return 0;
}
任务计划2
斜率优化做法。将原转移方程移项,让只含\(j\)的式子移到左边,其余移到右边,再将右边含\(j\)的式子提公因式,得到
\]
此时将外层循环到的\(i\)看做已知量(则关于\(i\)的变量\(t[i],c[i]\)为常数),看做一个斜率确定的一次函数\(y=kx+b\),其中\(f[j]\)看做函数的\(y\),\(c[j]\)看做函数的\(x\),\((t[i]+s)\)为斜率。要让\(f[i]\)最小即让此一次函数截距最小。
(图自ButterflyDew)
而容易得到:将此确定的斜率函数从最下面向上平移遇到的第一个点\((c[j],f[j])\)就是能取到最小截距(最优\(f[i]\))的点,(满足\(k_1\le k_0\le k_2\)),如图,也就是一个下凸壳的顶点。
而像这样的上凸壳顶点如图显然一定不会是最优解,所以我们维护一个下凸壳,每次找到顶点即为最优。
而这道题我们不需要维护整个下凸壳,而只维护下凸壳顶点及顶点右侧的点(因为左侧不可能比顶点优)。我们维护一个单调队列,使队首为下凸壳顶点,每次最优即为队首元素。维护时先将下凸壳顶点左边的所有点弹掉(若当前点与下一个点构成的直线斜率小于等于\(s+t[i]\),则当前点在左边),之后队首就是下凸壳的顶点,取出并算出的\(f[i]\)即为最优,最后再将所有构成上凸壳的点删去维护一下下凸壳。
单调队列部分实现代码:
while(l<r&&f[q[l+1]]-f[q[l]]<=(S+t[i])*(c[q[l+1]]-c[q[l]])) l++; // 弹出顶点左边的点
f[i]=f[q[l]]+t[i]*c[i]+S*c[n]-c[q[l]]*(S+t[i]);
while(l<r&&(f[i]-f[q[r]])*(c[q[r]]-c[q[r-1]])<=(f[q[r]]-f[q[r-1]])*(c[i]-c[q[r]])) r--; // 维护下凸壳
q[++r]=i;
完整代码:
#include <cstdio>
#include <cstring>
#define MIN(A,B) ((A)<(B)?(A):(B))
#define MAXN 5005*2
using namespace std;
int f[MAXN],q[MAXN];
int t[MAXN],c[MAXN];
int n,s;
int main(){
memset(f, 0x3f, sizeof(f));
f[0]=0;
scanf("%d\n%d", &n, &s);
for(int i=1;i<=n;++i){
int tt,tc;
scanf("%d %d", &tt, &tc);
t[i]=t[i-1]+tt;
c[i]=c[i-1]+tc;
}
int l=1,r=1;
for(int i=1;i<=n;++i){
while(l<r&&(f[q[l+1]]-f[q[l]])<=(t[i]+s)*(c[q[l+1]]-c[q[l]])) l++;
f[i]=f[q[l]]-c[q[l]]*(t[i]+s)+s*c[n]+c[i]*t[i];
while(l<r&&(f[q[r]]-f[q[r-1]])*(c[i]-c[q[r]])>=(f[i]-f[q[r]])*(c[q[r]]-c[q[r-1]])) r--;
q[++r]=i;
}
printf("%d", f[n]);
return 0;
}
任务安排3
因为\(T_i\)可能为负数,所以直线斜率\(s+t[i]\)不单增,所以不能直接单调队列取队首,而是二分查找出两条斜率为\(k_1,k_2\)的直线满足\(k_1\le s+t[i]\le k_2\),两条直线交点即为最优点。
#include <cstdio>
#include <cstring>
#define MIN(A,B) ((A)<(B)?(A):(B))
#define MAXN 300003
#define ll long long
using namespace std;
ll f[MAXN];
int q[MAXN];
ll t[MAXN],c[MAXN];
int n,s;
int l=1,r=1;
inline int query(ll k){
int L=l,R=r,ans;
while(L<=R){
int mid=(L+R)>>1;
if((f[q[mid]]-f[q[mid-1]])<=k*(c[q[mid]]-c[q[mid-1]])) L=mid+1,ans=mid;
else R=mid-1;
}
return q[ans];
}
int main(){
memset(f, 0x3f, sizeof(f));
f[0]=0;
scanf("%d\n%d", &n, &s);
for(int i=1;i<=n;++i){
ll tt,tc;
scanf("%lld %lld", &tt, &tc);
t[i]=t[i-1]+tt;
c[i]=c[i-1]+tc;
}
for(int i=1;i<=n;++i){
int j=query(t[i]+s);
f[i]=f[j]-c[j]*(t[i]+s)+s*c[n]+c[i]*t[i];
while(l<r&&
(f[q[r]]-f[q[r-1]])*(c[i]-c[q[r]])>=(f[i]-f[q[r]])*(c[q[r]]-c[q[r-1]])) r--;
q[++r]=i;
}
printf("%lld", f[n]);
return 0;
}
百日旅行
\(N\)天,如果连续\(x\)天旅游,则花费\(p\times x\times x\),否则连续\(x\)天吃饭,花费\(Q\times x\),问最小花费
设计dp,\(f[i]\)表示第\(i\)天最小花费并且这一天在旅游,\(g[i]\)表示在这一天吃饭,转移方程:
f[i]=min(g[j]+SQR(i-j)*p,f[i])
g[i]=min(f[j]+(i-j)*q,g[i])
观察\(g[i]\),\(g[i]=i*q+f[j]-j*q\),所以维护\(1\)到\(i-1\)的\(f[i]-i*p\)最小值即可。
观察\(f[i]\),\(f[i]=g[i]+p*i^2-2*p*i*j+p*j^2\)
移项,使只含\(j\)的式子在左边,其余右边,得\(g[j]+p*j^2=i*(2*p*j)+f[i]-p*i^2\)
此时看做一个一次函数,\(x=2*p*j,k=i,b=f[i]-p*i^2\),要想\(f[i]\)最小,即让截距最小,维护一个下凸壳。又发现斜率\(i\)单增,可使用单调队列。
#include <cstdio>
#include <algorithm>
#define ll long long
#define MAXN 200002
#define MIN(A,B) ((A)<(B)?(A):(B))
#define j (q[l])
#define SQR(A) ((A)*(A))
#define Y(A) (g[A]+P*(A)*(A))
#define X(A) ((A)*2*P)
using namespace std;
int n,l,r;
ll f[MAXN],g[MAXN],q[MAXN],P,Q;
int main(){
scanf("%d %lld %lld", &n, &P, &Q);
l=1,r=1;
ll t=0;
for(int i=1;i<=n;++i){
while(l<r&&(Y(q[l + 1]) - Y(q[l])) <= i*(X(q[l+1]) - X(q[l]))) ++l;
f[i]=g[j]+P*SQR(i-j);
g[i]=i*Q+t;
t=min(f[i]-i*Q,t);
while(l<r && (Y(q[r]) - Y(q[r-1])) * (X(i) - X(q[r])) >= (Y(i) - Y(q[r])) * (X(q[r]) - X(q[r-1]))) --r;
q[++r]=i;
}
printf("%lld", min(f[n], g[n]));
return 0;
}
/*
g[i]=i*q+f[j]-j*q
g[j]+p*j^2=i*(2*p*j)+f[i]-p*i^2
*/
DP斜率优化总结的更多相关文章
- 【BZOJ-4518】征途 DP + 斜率优化
4518: [Sdoi2016]征途 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 230 Solved: 156[Submit][Status][ ...
- 【BZOJ-3437】小P的牧场 DP + 斜率优化
3437: 小P的牧场 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 705 Solved: 404[Submit][Status][Discuss ...
- 【BZOJ-1010】玩具装箱toy DP + 斜率优化
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 8432 Solved: 3338[Submit][St ...
- 【BZOJ】1096: [ZJOI2007]仓库建设(dp+斜率优化)
http://www.lydsy.com/JudgeOnline/problem.php?id=1096 首先得到dp方程(我竟然自己都每推出了QAQ)$$d[i]=min\{d[j]+cost(j+ ...
- BZOJ 1096: [ZJOI2007]仓库建设(DP+斜率优化)
[ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在 ...
- 学渣乱搞系列之dp斜率优化
学渣乱搞系列之dp斜率优化 By 狂徒归来 貌似dp的斜率优化一直很难搞啊,尤其是像我这种数学很挫的学渣,压根不懂什么凸包,什么上凸下凸的,哎...说多了都是泪,跟wdd讨论了下,得出一些结论.本文很 ...
- HDU 3507 [Print Article]DP斜率优化
题目大意 给定一个长度为\(n(n \leqslant 500000)\)的数列,将其分割为连续的若干份,使得 $ \sum ((\sum_{i=j}^kC_i) +M) $ 最小.其中\(C_i\) ...
- dp斜率优化
算法-dp斜率优化 前置知识: 凸包 斜率优化很玄学,凭空讲怎么也讲不好,所以放例题. [APIO2014]序列分割 [APIO2014]序列分割 给你一个长度为 \(n\) 的序列 \(a_1,a_ ...
- BZOJ 1010: [HNOI2008]玩具装箱toy [DP 斜率优化]
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 9812 Solved: 3978[Submit][St ...
随机推荐
- Chart 文件结构
一个 Chart 包由以下几个配置文件组成: wordpress/ Chart.yaml # Yaml文件,用于描述 Chart 的基本信息,包括名称版本等 LICENSE # [可选] 文本格式的协 ...
- REDISTEMPLATE如何注入到VALUEOPERATIONS
REDISTEMPLATE如何注入到VALUEOPERATIONS 今天看到Spring操作redis 是可以将redisTemplate注入到ValueOperations,避免了ValueOpe ...
- 微信小程序---客服消息接口调用,拿来即用
如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 如果对你有帮助的话麻烦点个[推荐]~最好还可以follow一下我的GitHub~感谢观看! 在 ...
- python内置异常层次
内置异常 BaseException # 所有异常的基类 +-- SystemExit # 解释器请求退出 +-- KeyboardInterrupt # 用户中断执行(通常是输入^C) +-- Ge ...
- layui.js---layer;;前端预览pdf
layui.js---layer;;前端预览pdf 1.必须引入layui.js 2.uul是pdf文件地址 3.触发function函数:小于号button onclick="pdfsee ...
- LFS7.10——准备Host系统
转载请标明出处:https://www.cnblogs.com/kelamoyujuzhen/articles/9161515.html 实验环境: Host:Windows10 + WMWare W ...
- dns服务器正向解析配置
DNS服务器的配置 一.安装软件 1.安装bind.bind-utils软件,起服务,设置开机启动. bind-utils软件用于提供nslookup功能,用于测试dns是否搭建成功,能够正常解析. ...
- abp vNext微服务框架分析
本文转载自:https://www.cnblogs.com/william-xu/p/11245738.html abp vNext新框架的热度一直都很高,于是最近上手将vNext的微服务Demo做了 ...
- AspNetCore架构图
asp,net,core All-in-One App All-in-One applications N-Layer 典型的应用层 分层项目骨架 Clean Architecture Layers ...
- 本地安装部署Jira
https://blog.csdn.net/u013492736/article/details/83315650 1. 首先在官网下自行搭建服务器的版本,有适合于windows的,也有linux版本 ...