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

HDU 3507 Print Article

时间:2015-08-15 20:02:35      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:dp   dp优化   单调队列   

题目链接

斜率DP的入门题。

题意很清楚,就是输出序列a[n],把连续的单词放在同一行输出的费用是连续输出的单词费用和的平方加上常数M

一行的费用为cost=(C[i])2+M

让我们求这个费用的最小值。

SiCi 的前缀和。

设dp[i]表示输出前i个单词的最小费用,那么有如下的DP方程:

dp[i]=min(dp[j]+(Si?Sj)2)+M (0<j<i)

我们首先假设在算 dp[i] 时,k<j , j点比k点优。

也就是dp[j]+(Si?Sj)2<=dp[k]+(Si?Sk)2;

所谓jk优就是DP方程里面的值更小

对上述方程进行整理很容易得到:

(dp[j]+S2j)?(dp[k]+S2k)(Sj?Sk)<=2?Si
注意整理中要考虑下正负,涉及到不等号的方向。

左边我们发现如果令:

yj=dp[j]+S2j
xj=Sj

那么就变成了斜率表达式:yj?ykxj?xk<=sum[i];

而且不等式右边是递增的。

所以我们可以看出以下两点:我们令 g[k,j]=yj?ykxj?xk

第一:如果上面的不等式成立,那就说jk优,而且随着i的增大上述不等式一定是成立的,也就是对i以后算DP值时,j都比k优。那么k就是可以淘汰的。

第二:如果 k<j<i 而且 g[k,j]>g[j,i] 那么 j 是可以淘汰的。

假设 g[j,i]<sum[i]就是ij优,那么j没有存在的价值

相反如果 g[j,i]>sum[i] 那么同样有 g[k,j]>sum[i] 那么 kj优 那么 j 是可以淘汰的

所以这样相当于在维护一个下凸的图形,斜率在逐渐增大。

通过一个队列来维护。

#include <bits/stdc++.h>
using namespace std;
#define prt(k) cerr<<#k" = "<<k<<endl
typedef long long ll;
const ll inf = 0x3f3f3f3f;
const int N = 505000;
int M;
ll S[N];
int n;
ll dp[N];
ll Y(int j)
{
    return dp[j] + S[j] * S[j];
}
ll X(int j)
{
    return  S[j];
}
bool cmp(int k, int j, int i) // j tao tai
{   // k < j < i
    return (Y(j) - Y(k)) * (X(i) - X(j)) >=
    (Y(i) - Y(j)) * (X(j) - X(k));
}
int q[N];
ll sqr(ll x)
{
    return x * x;
}
int main()
{
    while (scanf("%d%d", &n, &M)==2) {
        S[0] = 0;
        for (int i=1;i<=n;i++) {
            int c; scanf("%d", &c);
            S[i] = S[i-1] + c;
        }
        dp[0] = 0;
        int head = 0, tail = -1;
        q[++tail] = 0;
        for (int i=1;i<=n;i++) {
            while (tail - head + 1 >= 2  ) {
                int k = q[head];
                int j = q[head+1];
                if (Y(j) - Y(k)<=2*S[i]*(X(j) - X(k))) {
                    head++;
                }
                else break;
            }
            int j = q[head];
            dp[i] = dp[j] + sqr(S[i] - S[j]) + M;
            while (tail - head + 1 >= 2) {
                int k = q[tail - 1];
                int j = q[tail];
                if (cmp(k, j, i)) tail--;
                else break;
            }
            q[++tail] = i;
        }
        printf("%I64d\n", dp[n]);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 3507 Print Article

标签:dp   dp优化   单调队列   

原文地址:http://blog.csdn.net/oilover/article/details/47682985

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