斜率优化DP:DP的一种优化形式,主要用于优化如下形式的DP

f[i]=f[j]+x[i]*x[j]+...

学习可以参考下面的博客:

https://www.cnblogs.com/Xing-Ling/p/11210179.html

https://blog.csdn.net/xiang_6/article/details/81450647

我的做法结合了这两种方案。

首先,用代数法求出进行状态更新的条件。

然后,判断上凸还是下凸。

在下一步,求出斜率,用于把起始且并不优的状态淘汰。

最后,就可以写代码了

主要题目:

loj10188装箱游戏

 1 #include<bits/stdc++.h>
2 #define rll register long long
3 using namespace std;
4 const int maxn=5e7+10;
5 typedef long long ll;
6 ll sum[maxn],f[maxn],q[maxn];
7 ll n,l,h=1,t=0;
8
9 inline ll min(rll a,rll b){return a<b?a:b;}
10 inline ll X(rll i){return sum[i]+i;}
11 inline ll Y(rll i){return f[i]+(sum[i]+i+1+l)*(sum[i]+i+1+l);}
12 inline long double xl(rll a,rll b){return (long double)(Y(b)-Y(a))/(X(b)-X(a));}
13
14 int main()
15 {
16 scanf("%lld%lld",&n,&l);
17 for(ll i=1;i<=n;++i)
18 {
19 scanf("%lld",sum+i);
20 sum[i]+=sum[i-1];
21 }
22 q[++t]=0;
23 for(ll i=1;i<=n;++i)
24 {
25 while(h<t && xl(q[h],q[h+1])<=2*(sum[i]+i))++h;
26 int j=q[h];
27 f[i]=f[j]+(sum[i]-sum[j]+i-j-1-l)*(sum[i]-sum[j]+i-j-1-l);
28 while(h<t && xl(q[t],i)<=xl(q[t-1],q[t]))t--;
29 q[++t]=i;
30 }
31 cout<<f[n];
32 return 0;
33 }

loj10189仓库建设

 1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int maxn = 1e6 + 10;
5 ll n;
6 ll x[maxn], sum[maxn], s[maxn], c[maxn], f[maxn];
7 ll tail, head, q[maxn];
8 inline ll X(ll a) { return sum[a]; }
9 inline ll Y(ll a) { return f[a] + s[a]; }
10 inline long double xl(ll a, ll b) { return (long double)(Y(b) - Y(a)) / (X(b) - X(a)); }
11
12 int main() {
13 scanf("%lld", &n);
14 for (ll p, i = 1; i <= n; ++i) {
15 scanf("%lld%lld%lld", x + i, &p, c + i);
16 sum[i] = sum[i - 1] + p;
17 s[i] = s[i - 1] + p * x[i];
18 }
19 tail = 0, head = 1;
20 q[++tail] = 0;
21 for (ll i = 1; i <= n; ++i) {
22 while (tail > head && xl(q[head], q[head + 1]) <= x[i]) ++head;
23 int j = q[head];
24 f[i] = f[j] + x[i] * (sum[i] - sum[j]) - s[i] + s[j] + c[i];
25 while (tail > head && xl(q[tail], i) <= xl(q[tail - 1], q[tail])) --tail;
26 q[++tail] = i;
27 }
28 cout << f[n];
29 return 0;
30 }

loj10190特别行动队

 1 #include <bits/stdc++.h>
2 using namespace std;
3 const int maxn = 1e6 + 10;
4 typedef long long ll;
5 ll q[maxn], h = 1, t = 0;
6 ll n, a, b, c, s[maxn], f[maxn];
7 inline ll X(ll i) { return s[i]; }
8 inline ll Y(ll i) { return f[i] + a * s[i] * s[i] - b * s[i]; }
9 inline long double xl(ll a, ll b) { return (long double)(Y(b) - Y(a)) / (X(b) - X(a)); }
10 int main() {
11 scanf("%lld%lld%lld%lld", &n, &a, &b, &c);
12 for (int i = 1; i <= n; ++i) {
13 scanf("%lld", s + i);
14 s[i] += s[i - 1];
15 }
16 q[++t] = 0;
17 for (int i = 1; i <= n; ++i) {
18 while (t > h && xl(q[h], q[h + 1]) >= 2 * a * s[i]) ++h;
19 int j = q[h];
20 f[i] = f[j] + a * (s[i] - s[j]) * (s[i] - s[j]) + b * (s[i] - s[j]) + c;
21 while (t > h && xl(q[t - 1], q[t]) <= xl(q[t], i)) --t;
22 q[++t] = i;
23 }
24 cout << f[n];
25 return 0;
26 }

loj10191打印文章

 1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int maxn = 5e5 + 10;
5 ll n, m;
6 ll s[maxn], f[maxn];
7 ll h, t, q[maxn];
8 inline ll X(ll i) { return s[i]; }
9 inline ll Y(ll i) { return f[i] + s[i] * s[i]; }
10 // inline long double xl(ll a,ll b){return (long double)(Y(b)-Y(a))/(X(b)-X(a));}
11 int main() {
12 while (scanf("%lld%lld", &n, &m) == 2) {
13 memset(s, 0, sizeof s);
14 memset(f, 0, sizeof f);
15 memset(q, 0, sizeof q);
16 h = 1, t = 0;
17 for (int i = 1; i <= n; ++i) {
18 scanf("%lld", s + i);
19 s[i] += s[i - 1];
20 }
21 q[++t] = 0;
22 for (int i = 1; i <= n; ++i) {
23 while (h < t && Y(q[h + 1]) - Y(q[h]) <= 2 * s[i] * (X(q[h + 1]) - X(q[h]))) ++h;
24 ll j = q[h];
25 f[i] = f[j] + (s[i] - s[j]) * (s[i] - s[j]) + m;
26 while (h < t &&
27 (Y(q[t]) - Y(q[t - 1])) * (X(i) - X(q[t])) >= (Y(i) - Y(q[t])) * (X(q[t]) - X(q[t - 1])))
28 --t;
29 q[++t] = i;
30 }
31 printf("%lld\n", f[n]);
32 }
33 return 0;
34 }

loj10192锯木厂选址

 1 #include <bits/stdc++.h>
2 using namespace std;
3 const int maxn = 2e5 + 10;
4 typedef long long ll;
5 ll n, dis[maxn], w[maxn], sw[maxn], swd[maxn], f[maxn][2];
6 ll h = 1, t, q[maxn];
7
8 inline ll x(ll i) { return sw[i]; }
9 inline ll y(ll i) { return f[i][0] + swd[i]; }
10
11 int main() {
12 scanf("%lld", &n);
13 for (ll d, i = 1; i <= n; ++i) {
14 scanf("%lld%lld", w + i, &d);
15 dis[i + 1] = dis[i] + d;
16 sw[i] = sw[i - 1] + w[i];
17 swd[i] = swd[i - 1] + w[i] * dis[i];
18 }
19 sw[n + 1] = sw[n];
20 swd[n + 1] = swd[n];
21 for (ll i = 2; i <= n; ++i) f[i][0] = dis[i] * sw[i] - swd[i];
22 q[++t] = 1;
23 for (ll i = 2; i <= n; ++i) {
24 while (h < t && y(q[h + 1]) - y(q[h]) <= dis[i] * (x(q[h + 1]) - x(q[h]))) ++h;
25 ll j = q[h];
26 f[i][1] = f[j][0] + dis[i] * (sw[i] - sw[j]) - (swd[i] - swd[j]);
27 while (h < t &&
28 (y(q[t]) - y(q[t - 1])) * (x(i) - x(q[t])) >= (y(i) - y(q[t])) * (x(q[t]) - x(q[t - 1])))
29 --t;
30 q[++t] = i;
31 }
32 ll ans = (ll)1 * 100000000 * 100000000;
33 for (int i = 1; i <= n; ++i)
34 if (ans > f[i][1] + dis[n + 1] * (sw[n + 1] - sw[i]) - (swd[n + 1] - swd[i]))
35 ans = f[i][1] + dis[n + 1] * (sw[n + 1] - sw[i]) - (swd[n + 1] - swd[i]);
36 cout << ans;
37
38 return 0;
39 }

loj10184任务安排1

 1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int maxn = 5e3 + 10;
5 ll n, s;
6 ll f[maxn], sc[maxn], st[maxn];
7
8 int main() {
9 scanf("%lld%lld", &n, &s);
10 for (int i = 1; i <= n; ++i) {
11 scanf("%lld%lld", st + i, sc + i);
12 st[i] += st[i - 1];
13 sc[i] += sc[i - 1];
14 }
15 for (int i = n; i > 0; --i) {
16 f[i] = (st[n] + s) * (sc[n] - sc[i - 1]);
17 for (int j = i + 1; j <= n; ++j) {
18 if (f[i] > f[j] + st[j - 1] * (sc[j - 1] - sc[i - 1]) + (sc[n] - sc[i - 1]) * s)
19 f[i] = f[j] + st[j - 1] * (sc[j - 1] - sc[i - 1]) + (sc[n] - sc[i - 1]) * s;
20 }
21 }
22 cout << f[1];
23 return 0;
24 }

loj10185任务安排2

 1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int maxn = 1e4 + 10;
5 ll n, s;
6 ll f[maxn], sc[maxn], st[maxn];
7
8 int main() {
9 scanf("%lld%lld", &n, &s);
10 for (int i = 1; i <= n; ++i) {
11 scanf("%lld%lld", st + i, sc + i);
12 st[i] += st[i - 1];
13 sc[i] += sc[i - 1];
14 }
15 for (int i = n; i > 0; --i) {
16 f[i] = (st[n] + s) * (sc[n] - sc[i - 1]);
17 for (int j = i + 1; j <= n; ++j) {
18 if (f[i] > f[j] + st[j - 1] * (sc[j - 1] - sc[i - 1]) + (sc[n] - sc[i - 1]) * s)
19 f[i] = f[j] + st[j - 1] * (sc[j - 1] - sc[i - 1]) + (sc[n] - sc[i - 1]) * s;
20 }
21 }
22 cout << f[1];
23 return 0;
24 }

一本通提高篇——斜率优化DP的更多相关文章

  1. 【笔记篇】斜率优化dp(一) HNOI2008玩具装箱

    斜率优化dp 本来想直接肝这玩意的结果还是被忽悠着做了两道数论 现在整天浑浑噩噩无心学习甚至都不是太想颓废是不是药丸的表现 各位要知道我就是故意要打删除线并不是因为排版错乱 反正就是一个del标签嘛并 ...

  2. 总结-一本通提高篇&算竞进阶记录

    当一个人看见星空,就再无法忍受黑暗 为了点亮渐渐沉寂的星空 不想就这样退役 一定不会鸽の坑 . 一本通提高篇 . 算竞进阶 . CDQ & 整体二分 . 平衡树 . LCT . 字符串 . 随 ...

  3. 蒟蒻关于斜率优化DP简单的总结

    斜率优化DP 题外话 考试的时候被这个玩意弄得瑟瑟发抖 大概是yybGG的Day4 小蒟蒻表示根本不会做..... 然后自己默默地搞了一下斜率优化 这里算是开始吗?? 其实我讲的会非常非常非常简单,, ...

  4. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  5. bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

    题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L ...

  6. [BZOJ3156]防御准备(斜率优化DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3156 分析: 简单的斜率优化DP

  7. 【BZOJ-1096】仓库建设 斜率优化DP

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3719  Solved: 1633[Submit][Stat ...

  8. BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

    1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...

  9. BZOJ 3156: 防御准备 斜率优化DP

    3156: 防御准备 Description   Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小的战 ...

随机推荐

  1. [leetcode]242. Valid Anagram判断两个字符串是不是包含相同字符的重排列

    /* 思路是判断26个字符在两个字符串中出现的次数是不是都一样,如果一样就返回true. 记住这个方法 */ if (s.length()!=t.length()) return false; int ...

  2. java开发手册之哨兵语句

    if(条件判断1){ return; } if(条件判断2){ return; } //do  another things 注意事项:一定要避免多个if else 判断 带来逻辑混乱 可读性变差

  3. 如何在 Linux 系统查询机器最近重启时间

    如何在 Linux 系统查询机器最近重启时间 在你的 Linux 或类 UNIX 系统中,你是如何查询系统上次重新启动的日期和时间?怎样显示系统关机的日期和时间? last 命令不仅可以按照时间从近到 ...

  4. lambda表达式初识

    简单来说,一般提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数. 而匿名函数就是没有名字的函数,有时函数只是临时一用,而且它的业务逻辑也相 ...

  5. Redis 设计与实现 9:五大数据类型之集合

    集合对象的编码有两种:intset 和 hashtable 编码一:intset intset 的结构 整数集合 intset 是集合底层的实现之一,从名字就可以看出,这是专门为整数提供的集合类型. ...

  6. java.io.NotSerializableException: org.apache.kafka.clients.consumer.ConsumerRecord

    kafka 与spark集成 序列化问题 sparkConf.set("spark.serializer", "org.apache.spark.serializer.K ...

  7. 九个最容易出错的 Hive sql 详解及使用注意事项

    阅读本文小建议:本文适合细嚼慢咽,不要一目十行,不然会错过很多有价值的细节. 文章首发于公众号:五分钟学大数据 前言 在进行数仓搭建和数据分析时最常用的就是 sql,其语法简洁明了,易于理解,目前大数 ...

  8. 【老孟Flutter】为什么 build 方法放在 State 中而不是在 StatefulWidget 中

    老孟导读:此篇文章是生命周期相关文章的番外篇,在查看源码的过程中发现了这一有趣的问题,欢迎大家一起探讨. Flutter 中Stateful 组件的生命周期:http://laomengit.com/ ...

  9. MATLAB OPC错误OPCenum service is not operating correctly解决办法

    错误截图: 出错原因:C:\Windows\SysWOW64下没有OpcEnum.exe等文件,opc需要这些文件才能正常运行.有些系统内置了,有些系统没有. 解决方法:去opc官网https://o ...

  10. 【Flutter】可滚动组件之SingleChildScrollView

    前言 SingleChildScrollView类似于Android中的ScrollView,它只能接收一个子组件. 接口描述 const SingleChildScrollView({ Key ke ...