zoukankan      html  css  js  c++  java
  • CDOJ 879 摩天轮 dp+斜率优化

    原题链接:http://www.acm.uestc.edu.cn/#/problem/show/879

    题意:

    中文题

    题解:

     这是一道斜率dp的题。

    先把$a$数组排个序。

    令$dp[i][j]$表示第$i$个人坐在第$j$个箱子里面的最优解。

    容易得到以下转移方程:

    $$dp[i][j]=min left { dp[k][j-1]+(a[i]-a[k+1])^2  ight }$$

    观察这个式子,发现好像可以斜率优化:

    若$u>v$且$u$要比$v$优,即:

    $$dp[u][j-1]+(a[i]-a[u+1])^2<dp[v][j-1]+(a[i]-a[v+1])^2$$

    整理后可得到下式:

    $$frac {dp[u][j-1]+a[u+1]^2-(dp[v][j-1]+a[v+1]^2)} {a[u+1]-a[v+1]} < 2*a[i]$$

    $$Y(t)=dp[t][j-1]+a[t+1]^2$$

    $$X(t)=a[t+1]$$

    那么原式就是:

    $$frac {Y(u)-Y(v)} {X(u)-X(v)} <2*a[i]$$

    这是一个描述斜率的东西,它表明,如果$u,v$的斜率小于$2*a[i]$,那么$u$一定比$v$更优,否则$v$不比$u$差。

    令$S(u,v)=frac {Y(u)-Y(v)} {X(u)-X(v)}$,那么如果$S(u,v)<S(v,w)$,那么$b$一定是没用的状态,这是因为假如$S(u,v)<2*a[i]$,那么$u$比$v$更优,如果$S(u,v) geq 2*a[i]$,那么$S(v,w) geq 2*a[i]$,那么$w$不比$v$差。所以$v$就是没用的节点。

    综上,我们可以通过一个双端队列来维护一个下凸包,向队尾插入值,维护队尾的单调性。从队首寻找答案。

    代码:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #define MAX_N 100005
    using namespace std;
    
    int n,m;
    int w[MAX_N];
    
    int dp[MAX_N][2];
    
    double Y(int t,int j){
        return dp[t][j]+w[t+1]*w[t+1];
    }
    
    double X(int t){
        return w[t+1];
    }
    
    double Slope(int u,int v,int j) {
        if (X(u) == X(v))return 1e233;
        return (Y(u, j) - Y(v, j)) / (X(u) - X(v));
    }
    
    int que[MAX_N];
    
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)scanf("%d", &w[i]);
        sort(w + 1, w + 1 + n);
        for (int i = 1; i <= n; i++)dp[i][1] = (w[i] - w[1]) * (w[i] - w[1]);
        for (int j = 2; j <= m; j++) {
            int cur = j & 1;
            int front = 0, rear = 0;
            que[rear++] = 1;
            for (int i = 2; i <= n; i++) {
                while (rear - front > 1 && Slope(que[front], que[front + 1], cur ^ 1) <= 2 * w[i])
                    front++;
                dp[i][cur] = dp[que[front]][cur ^ 1] + (w[i] - w[que[front] + 1]) * (w[i] - w[que[front] + 1]);
                while (rear - front > 1 && Slope(que[rear - 1], que[rear - 2], cur ^ 1) >= Slope(i, que[rear - 1], cur ^ 1))
                    rear--;
                que[rear++] = i;
            }
        }
        printf("%d
    ", dp[n][m & 1]);
        return 0;
    }
  • 相关阅读:
    基础才是重中之重~stream和byte[]的概念与转化
    微信扫码i支付~官方DEMO的坑
    知方可补不足~SqlServer自动备份数据库及清理备份文件
    11g r2 模拟OCR和voting disk不可用,完整恢复过程,以及一些注意事项
    自定义navigationBar的高度
    Python 中的用户自定义类型
    hdu1370-Biorhythms
    Ruby on Rails 實戰聖經阅读(三)
    重新配置与卸载 11gR2 Grid Infrastructure
    非确定有限状态自动机的构建(一)——NFA的定义和实现
  • 原文地址:https://www.cnblogs.com/HarryGuo2012/p/4841215.html
Copyright © 2011-2022 走看看