• BZOJ 1010 斜率优化DP


    题意:

    http://www.lydsy.com/JudgeOnline/problem.php?id=1010

    思路:

    DP方程不难想:
    DP[I]=MIN(DP[J]+(SUM[I]-SUM[J]+I-J-1-L)^2) ,J<I
    其中DP[I]表示处理到第I个玩具时最少的费用。

    直接来显然TLE,一维方程一般用斜率优化。


    先化简下方程:
    令F[I]=SUM[I]+I,C=1+L,则化为
    DP[I]=MIN(DP[J]+(F[I]-F[J]-C)^2)

    以下是用这方法的步骤:
    1.证明较优决策点对后续状态影响的持续性
    假设在状态I处,有两个决策点J,K(J<K),且决策K比决策J好,即
       DP[K]+(F[I]-F[K]-C)^2<=DP[J]+(F[I]-F[J]-C)^2
    则,对于状态I之后的某状态T,  F[T]=F[I]+V
    要证
    DP[K]+(F[T]-F[K]-C)^2<=DP[J]+(F[T]-F[J]-C)^2
    只需证
    DP[K]+(F[I]+V-F[K]-C)^2<=DP[J]+(F[I]+V-F[J]-C)^2
    只需证
    DP[K]+(F[I]-F[K]-C)^2+2*(F[I]-F[K]-C)*V+V^2<=DP[J]+(F[I]-F[J]-C)^2+2*(F[I]-F[J]-C)*V+V^2
    联系假设只需要证:
    2*(F[I]-F[K]-C)*V<=2*(F[I]-F[J]-C)*V
    即证:
    F[K]>=F[J]
    F[I]显然为增函数,且J<K,所以上式得证.

    2.求斜率方程:一般化为左边是J,K,右边是I的形式
    由DP[K]+(F[I]-F[K]-C)^2<=DP[J]+(F[I]-F[J]-C)^2
    展开得:
    DP[K]+F[I]^2-2*F[I]*(F[K]+C)+(F[K]+C)^2<=DP[J]+F[I]^2-2*F[I]*(F[J]+C)+(F[J]+C)^2
    即:
    DP[K]+(F[K]+C)^2-DP[J]-(F[J]+C)^2<=2*F[I]*(F[K]-F[J])

    (DP[K]+(F[K]+C)^2-DP[J]-(F[J]+C)^2)/(2*(F[K]-F[J]))<=F[I]

    G(K,J)=DP[K]+(F[K]+C)^2-DP[J]-(F[J]+C)^2
    S(K,J)=2*(F[K]-F[J])
    X(K,J)=G(K,J)/S(K,J)
    所以斜率方程为X(K,J)<=F[I]


    3.规定队列的维护规则
    队首维护:
        假设A,B(A<B)是队首元素,若X(B,A)<=F[I],则B比A好,删除A,否则不需维护.

    队尾维护:
        假设A,B,C(A<B<C)是队尾元素
    a.若X(B,A)<=F[I],且X(C,B)<=F[I],则C比B好,B比A好
    b.若X(B,A)<=F[I],且X(C,B)>F[I],则B比C好,B比A好,B为极大值
    c.若X(B,A)>F[I],A比B好

    a,c情况直接删掉B,b情况保留.b情况可改为X(B,A)<X(C,B)

    以上内容转自:http://blog.sina.com.cn/s/blog_5f5353cc0100jx41.html

    自我总结:

    斜率优化的题前提还是很多的。。

    正如风炎大神说的:

    1.证明较优决策点对后续状态影响的持续性

    2.求斜率方程:一般化为左边是J,K,右边是I的形式

    3.规定队列的维护规则(这个规则实质上是在维护一个凸性函数,此题为下凸函数,所有转移的点都是凸性函数上的点,而这个凸性函数上的点又符合“较优决策点对后续状态影响的持续性”)

    4.此题满足决策单调,转移时0(1)的,对于一些决策不单调的,可以用数据结构做到0(logn)的

    View Code
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <cstdlib>
     5 #include <algorithm>
     6 
     7 #define N 55000
     8 
     9 using namespace std;
    10 
    11 int n;
    12 long long c,sum[N],f[N],dp[N];
    13 int q[N];
    14 
    15 inline void read()
    16 {
    17     scanf("%d%lld",&n,&c); c+=1;
    18     for(int i=1;i<=n;i++)
    19     {
    20         scanf("%lld",&sum[i]);
    21         sum[i]+=sum[i-1];
    22         f[i]=sum[i]+(long long)i;
    23     }
    24 }
    25 
    26 inline long long S(int x,int y)
    27 {
    28     return 2*(f[x]-f[y]);
    29 }
    30 
    31 inline long long G(int x,int y)
    32 {
    33     return dp[x]-dp[y]+(f[x]+c)*(f[x]+c)-(f[y]+c)*(f[y]+c);
    34 }
    35 
    36 inline void go()
    37 {
    38     int h=1,t=2;
    39     q[1]=0;
    40     for(int i=1;i<=n;i++)
    41     {
    42         while(h<t-1&&G(q[h+1],q[h])<=S(q[h+1],q[h])*f[i]) h++;
    43         dp[i]=dp[q[h]]+(f[i]-f[q[h]]-c)*(f[i]-f[q[h]]-c);
    44         while(h<t-1&&G(i,q[t-1])*S(q[t-1],q[t-2])<=G(q[t-1],q[t-2])*S(i,q[t-1])) t--;
    45         q[t++]=i;
    46     }
    47     printf("%lld\n",dp[n]);
    48 }
    49 
    50 int main()
    51 {
    52     read();
    53     go();
    54     return 0;
    55 }

    PS:BZOJ 好似不能用__int64,一用就CE

  • 相关阅读:
    Flask笔记:cookie
    Flask笔记:文件上传
    Python内置库:threading(多线程操作)
    Linux服务器架设篇,DNS服务器(三),正反解区域的配置
    Linux服务器架设篇,Windows中的虚拟机linux上不了外网怎么办?
    Linux服务器架设篇,DNS服务器(二),cache-only DNS服务器的搭建
    Linux服务器架设篇,DNS服务器(一),基础知识
    Linux网络架设篇,虚拟机l系统中网卡设备名与配置文件不符如何处理?
    Linux网络安全篇,FTP服务器的架设
    Linux基础管理篇,软件管理程序,yum与rpm
  • 原文地址:https://www.cnblogs.com/proverbs/p/2713109.html
Copyright © 2020-2023  润新知