zoukankan      html  css  js  c++  java
  • [JZOJ P1329] [DP]玩具装箱

    找了好几个大神的博客,然而一堆堆的公式看都看不懂,最后找到了hzwer学长的,第一次看到斜率优化,大概是假设两个k,j决策且k优于j,化成一堆公式,左边跟k,j有关,右边跟i有关。

    dp公式很好想, dp[i]=min(dp[j]+(i-j-1-l+sum[i]-sum[j])^2);(j<i)

    dp[i]表示前i个玩具的最优费用,dp[i]的值就取决于 dp[j]+从j+1到i玩具的费用 i-j-1 就可以得出。

    设f[i]=sum[i]+i,        c=1+l;

    dp[i]=min(dp[j]++(f[i]-f[j]-c)^2);

    证明决策单调性:

    假设在状态i处有k和j两种决策,且k优于j

    则 dp[k]+(f[i]-f[k]-c)^2<=dp[j]+(f[i]-f[j]-c)^2

    在状态i后的状态t也一定是k决策优于j决策

    dp[k]+(f[t]-f[k]-c)^2<=dp[j]+(f[t]-f[j]-c)^2

    f[t]=sum[t]+t=sum[i]+sum[t]-sum[i]+i+t-i;

    设 v=sum[t]-sum[i]+t-i;

    f[t]=f[i]+v;

    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*v*(f[i]-f[k]-c)+v^2<=dp[j]+(f[i]-f[j]-c)^2+2*v*(f[i]-f[j]-c)+v^2

    2*v*(f[i]-f[k]-c)<=2*v*(f[i]-f[j]-c)

    f[k]>=f[j]

    求斜率方程:

    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]-2*f[i]*(f[k]+c)+(f[k]+c)^2<=dp[j]-2*f[i]*(f[j]+c)+(f[j]+c)^2

    (dp[k]+(f[k]+c)^2-dp[j]-(f[j]+c)^2)/2*(f[k]-f[j])<=f[i]

    当 队首+1优于队首时      ->SLOP(队首+1=k,队首=j)  踢出队首

    这酱紫队首为最优,求出dp[i]

    把i加入决策中时 当 SLOP(i=k,队尾=j)<SLOP(队尾=k,队尾-1=j)  踢出队尾

    把决策i加入队尾。

    重要的一点是long long 因为要平方谁也不知道平方后的数有多可怕。不平方只过了样例没过一组数据我不想说话。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    long long  n,l,cc[50005],dp[50005],q[50005],f[50005],c;
    int head=1,tail=0;
    double solve(int j,int k)
    {
        return(dp[k]-dp[j]+(f[k]+c)*(f[k]+c)-(f[j]+c)*(f[j]+c))/(2.0*(f[k]-f[j]));
    }
    int main(){
        cin>>n>>l;
        for(int i=1;i<=n;i++)
            cin>>cc[i];
        for(int i=1;i<=n;i++)
            f[i]=f[i-1]+cc[i];
        for(int i=1;i<=n;i++)
            f[i]+=i;
        c=1+l;
        q[++tail]=0;
        for(int i=1;i<=n;i++)
        {
            while(head<tail&&solve(q[head],q[head+1])<=f[i])    head++;
            int t=q[head];
            dp[i]=dp[t]+(f[i]-f[t]-c)*(f[i]-f[t]-c);
            while(head<tail&&solve(q[tail],i)<solve(q[tail-1],q[tail]))
                tail--;
            q[++tail]=i;
        }
        cout<<dp[n];
        return 0;
    }
    嗯?你又来看code?
    No matter how you feel, get up , dress up , show up ,and never give up.
  • 相关阅读:
    docker 的使用
    WEB应用支持RESTFUL风格方法
    tomcat7 安装 windows 服务
    获取POM.XML依赖的JAR包
    集成 dubbo 微服务
    linux 修改yum 为阿里云源
    poj3904
    2013 ACM/ICPC 长春网络赛E题
    2013 ACM/ICPC 长春网络赛F题
    2013 ACM/ICPC 长沙网络赛J题
  • 原文地址:https://www.cnblogs.com/Kaike/p/6337315.html
Copyright © 2011-2022 走看看