• 一本通提高篇——斜率优化DP


    斜率优化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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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
    ", f[n]);
    32     }
    33     return 0;
    34 }
    View Code

    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 }
    View Code

    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 }
    View Code

    loj10185任务安排2

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn=1e4+10;
     5 int n,s;
     6 int f[maxn],sc[maxn],smt[maxn];
     7 int q[maxn],l,r;
     8 ll y(int a)
     9 {
    10     return f[a]+sc[a]*smt[a];
    11 }
    12 long double get_xl(int a,int b)
    13 {
    14     return (long double)(y(b)-y(a))/(smt[b]-smt[a]);
    15 }
    16 int main()
    17 {
    18     scanf("%d%d",&n,&s);
    19     for(int t,c,i=1;i<=n;++i)
    20     {
    21         scanf("%d%d",&smt[i],&sc[i]);
    22         smt[i]+=smt[i-1];
    23         sc[i]+=sc[i-1];
    24     }
    25     for(int i=n;i>=0;--i)
    26     {
    27         while(l<r&&get_xl(q[l],q[l+1])>=sc[i])++l;
    28         f[i]=f[q[l]]+(sc[q[l]]-sc[i])*smt[q[l]]+(sc[n]-sc[i])*s;
    29         while(l<r&&get_xl(q[r-1],q[r])<=get_xl(q[r],i))--r;
    30         q[++r]=i;
    31     }
    32     cout<<f[0]<<endl;
    33     return 0;
    34 }
    View Code
  • 相关阅读:
    eclipse 字体设置 Courier New字
    求百分比
    往数据库中插入固定数量的数据
    查看oracle连接数
    c# 简单的一个记事本
    控制台下,查看端口状态命令
    c++ 字符型转整型
    浅析vc6.0的辅助编程工具
    连连看辅助工具
    驱动精灵(Driver Genius Professional Edition 2007) v7.1.622 完美注册版(可升级)
  • 原文地址:https://www.cnblogs.com/gryzy/p/13129240.html
Copyright © 2020-2023  润新知