[DP优化方法之斜率DP]

什么是斜率dp呢 大概就把一些单调的分组问题 从O(N^2)降到O(N) 具体的话我就不多说了 看论文:

http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html

我自己也补充几句:

其实斜率dp有很多种打法 有凸包 有截距 有直接比较斜率的 因为我比较弱 所以的话就学最弱智的比较斜率的 听wph说截距很好理解

然后的话 讲课的时候scy说什么要证单调性什么鬼的 我在学的过程中好像没遇到就不管了 虽然我很弱 反正我能AC就行了

我们要知道的一点是我们要维护的是斜率递增还是递减的 这很重要

我做这种题就是 先枚举k<j<i 然后列出式子化简 变成(.....) / (.....)  < 或者 > x[i] 然后设两条斜率为g[i,j] g[j,k]

看看g[i,j]<g[j,k] 或者 g[i,j]>g[j,k]的情况 看看有没有使j最不优的情况删掉j 然后描出这个队列里面合法的点 就知道是单调递增还是递减了

其实我说的很乱 别看好了 直接上例题

[Usaco2008 Mar]土地购买

首先这一道题是求max的 我们自然要办法处理一下 先按x和y从小到大排序 我们发现 当i>j xi>xj yi>yj的时候 j是废的 所以我们要重新搞一遍 使得xi>xj yi<yj

这样就变成了x递增y递减的东西

然后斜率dp搞一下就好了 注意如果没删去那些没用的直接搞会错的 因为如果假设i>j i对于j来说j是废的 那么的话F[i]就是继承F[j] 就是把i和j分成两组 然后的话j又比j-1优(会有可能的好像我想了一下) 所以的话就继承了j的使原来不优 但是的话j-1不优是因为Y[j-1+1]的影响了 (想一下 我就因为这个wa了)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<climits>
#define Maxn 50010
using namespace std;
pair<double,double>pr[Maxn]; int N;
bool Cmp(const pair<double,double> &x,const pair<double,double> &y){if(x.first!=y.first) return x.first<y.first; return x.second<y.second;}
pair<double,double>S[Maxn]; int top=0; int Q[Maxn],head,tail; double F[Maxn];
inline double Slop(int j,int k){return (F[j]-F[k])/(S[k+1].second-S[j+1].second);}
int main()
{
  scanf("%d",&N); for(int i=1;i<=N;i++) scanf("%lf%lf",&pr[i].first,&pr[i].second);
  sort(pr+1,pr+N+1,Cmp); S[0]=make_pair(0,LLONG_MAX);
  for(int i=1;i<=N;i++){while(pr[i].second>=S[top].second) top--; S[++top]=pr[i];}
  head=1; tail=1; Q[head]=0;
  for(int i=1;i<=top;i++)
  {
    while(head<tail&&Slop(Q[head],Q[head+1])<=S[i].first) head++;
    F[i]=F[Q[head]]+S[i].first*S[Q[head]+1].second;
    while(head<tail&&Slop(Q[tail-1],Q[tail])>=Slop(Q[tail],i)) tail--; Q[++tail]=i;
  }
  return printf("%.0lf\n",F[top]),0;
}
/*
4
100 1
15 15
20 5
1 100
1<=N<=50000
*/

时间: 2024-10-05 06:17:20

[DP优化方法之斜率DP]的相关文章

HDU 3507 Print Article(斜率DP优化)

Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate t

常见的DP优化类型

常见的DP优化类型 1单调队列直接优化 如果a[i]单调增的话,显然可以用减单调队列直接存f[j]进行优化. 2斜率不等式 即实现转移方程中的i,j分离.b单调减,a单调增(可选). 令: 在队首,如果g[j,k]>=-a[i],那么j优于k,而且以后j也优于k,因此k可以重队列中直接删去.在队尾,如果x<y<z,且g[x,y]<=g[y,z],也就是说只要y优于x一定可以得出z优于y的,我们就删去y. 经过队尾的筛选,我们在队列中得到的是一个斜率递减的下凸包,每次寻找从上往下被-

bzoj 3156 防御准备(斜率DP)

3156: 防御准备 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 837  Solved: 395[Submit][Status][Discuss] Description Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小的战线花费值. Sample Input 10 2 3 1 5 4 5 6 3 1 2 Sample Output 18 HIN

hdu 3507 斜率dp

不好理解,先多做几个再看 此题是很基础的斜率DP的入门题. 题意很清楚,就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 设dp[i]表示输出前i个的最小费用,那么有如下的DP方程: dp[i]= min{ dp[j]+(sum[i]-sum[j])^2 +M }  0<j<i 其中 sum[i]表示数字的前i项和. 相信都能理解上面的方程. 直接求解上面的方程的话复杂度是O(n^2) 对于500000的规模显然是超时的.下面讲解下如何用斜率

loj6171/bzoj4899 记忆的轮廊(期望dp+优化)

题目: https://loj.ac/problem/6171 分析: 设dp[i][j]表示从第i个点出发(正确节点),还可以有j个存档点(在i点使用一个存档机会),走到终点n的期望步数 那么 a[i][k]表示i点为存档点,从i点走到k点(正确节点)的期望步数(中间没有其它存档点) 那么a[i][j]可以递推预处理出 其中g[v]表示从一个错误节点v开始走,期望走g[v]步会读档 解方程可以解出 s[j-1]就是点j-1出去的所有错误儿子的g[v]之和 那么接下来只要知道如何求g[v]就行了

bzoj 3851: 2048 dp优化

3851: 2048 Time Limit: 2 Sec  Memory Limit: 64 MBSubmit: 22  Solved: 9[Submit][Status] Description Teacher Mai is addicted to game 2048. But finally he finds it's too hard to get 2048. So he wants to change the rule: You are given some numbers. Every

HDU 3480 - Division - [斜率DP]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3480 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others) Little D is really interested in the theorem of sets recently. There's a problem that confused him a long time.   

「kuangbin带你飞」专题二十 斜率DP

layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 - 斜率DP 传送门 A.HDU - 3507 Print Article 题意 就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 题解 概率DP的入门题,把我搞得要死要活的. 首先dp[i]表示输出前i

【总结】DP优化

斜率优化 对形如: \[ f_i=min/max \{f_j+w_{i,j} \} \] \[ 更确切地,为形如f_i=min/max_{j<i}\{f_j+g_1(i)*g_2(j)+h_1(i)+h_2(j)\} \] \[ (关键在于含有关于i,j的函数的乘积g_1(i)*g_2(j)) \] 的dp方程可使用斜率优化 移项,得: \[ f_j+h_2(j)=g1(i)*g_2(j)+f_i-h_1(i) \] \(则f_i-h_1(i)可以看做是用斜率为g_1(i)的直线去截坐标系上的点