码迷,mamicode.com
首页 > 其他好文 > 详细

CDOJ 879 摩天轮 dp+斜率优化

时间:2015-09-26 21:12:16      阅读:259      评论:0      收藏:0      [点我收藏+]

标签:

原题链接: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 \right \}$$

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

若$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\n", dp[n][m & 1]);
    return 0;
}

 

CDOJ 879 摩天轮 dp+斜率优化

标签:

原文地址:http://www.cnblogs.com/HarryGuo2012/p/4841215.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!