zoukankan      html  css  js  c++  java
  • hdu 4258 Covered Walkway

    题目大意:

    一个N个点的序列,要将他们全部覆盖,求总最少费用;费用计算: c+(x-y)2

    分析:

    斜率优化DP

    我们假设k<j<i。如果在j的时候决策要比在k的时候决策好,那么也是就是dp[j]+M+(sum[i]-sum[j])^2<dp[k]+M+(sum[i]-sum[k])^2。(因为是最小花费嘛,所以优就是小于)

    两边移项一下,得到:(dp[j]+num[j]^2-(dp[k]+num[k]^2))/(2*(num[j]-num[k]))<sum[i]。我们把dp[j]-num[j]^2看做是yj,把2*num[j]看成是xj。

    那么不就是yj-yk/xj-xk<sum[i]么?   左边是不是斜率的表示? 

    那么yj-yk/xj-xk<sum[i]说明了什么呢?  我们前面是不是假设j的决策比k的决策要好才得到这个表示的? 如果是的话,那么就说明g[j,k]=yj-jk/xj-xk<sum[i]代表这j的决策比k的决策要更优。

    关键的来了:现在从左到右,还是设k<j<i,如果g[i,j]<g[j,k],那么j点便永远不可能成为最优解,可以直接将它踢出我们的最优解集。为什么呢?

    我们假设g[i,j]<sum[i],那么就是说i点要比j点优,排除j点。

    如果g[i,j]>=sum[i],那么j点此时是比i点要更优,但是同时g[j,k]>g[i,j]>sum[i]。这说明还有k点会比j点更优,同样排除j点。

    排除多余的点,这便是一种优化!

    接下来看看如何找最优解。

    设k<j<i。

    由于我们排除了g[i,j]<g[j,k]的情况,所以整个有效点集呈现一种上凸性质,即k j的斜率要大于j i的斜率。

    这样,从左到右,斜率之间就是单调递减的了。当我们的最优解取得在j点的时候,那么k点不可能再取得比j点更优的解了,于是k点也可以排除。换句话说,j点之前的点全部不可能再比j点更优了,可以全部从解集中排除。

    于是对于这题我们对于斜率优化做法可以总结如下:

    1,用一个单调队列来维护解集。

    2,假设队列中从头到尾已经有元素a b c。那么当d要入队的时候,我们维护队列的上凸性质,即如果g[d,c]<g[c,b],那么就将c点删除。直到找到g[d,x]>=g[x,y]为止,并将d点加入在该位置中。

    3,求解时候,从队头开始,如果已有元素a b c,当i点要求解时,如果g[b,a]<sum[i],那么说明b点比a点更优,a点可以排除,于是a出队。最后dp[i]=getDp(q[head])。

    原文链接  http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html

    对于这道题: f[i] = min(f[j] + (a[i]-a[j+1]) ^ 2+c) (N^2)

    公式变形+数形结合:f[i] = min{f[j] + a[j+1]^2 - 2*a[i]*a[j+1] + a[i]^2 +C}

    令x = a[j+1],y = f[j] + a[j+1]^2;

    f[i] = y - 2*a[i]*x + a[i]^2 + C;

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<queue>
     7 #define maxn 1000005
     8 using namespace std;
     9 typedef long long LL;
    10 LL n,a[maxn];
    11 LL dp[maxn];
    12 int que[maxn];
    13 double judge_k(int x,int y)
    14 {
    15     return (double)(dp[x]+a[x+1]*a[x+1]-(dp[y]+a[y+1]*a[y+1]))/((double)(2.0*(a[x+1]-a[y+1])));
    16 }
    17 int main()
    18 {
    19     int c;
    20     while(scanf("%I64d %d",&n,&c)!=EOF)
    21     {
    22         if(n==0&&c==0)
    23             break;
    24         for(int i=1;i<=n;i++)
    25             scanf("%I64d",&a[i]);
    26         dp[0]=0;dp[1]=c;
    27         que[0]=0;
    28         que[1]=1;
    29         int l=0,r=1;
    30         for(int i=2;i<=n;i++)
    31         {
    32             while(l<r&&judge_k(que[l],que[l+1])<=a[i]) l++;
    33             dp[i]=dp[que[l]]+c+(a[i]-a[que[l]+1])*(a[i]-a[que[l]+1]);
    34             while(l<r&&judge_k(que[r],i)<=judge_k(que[r],que[r-1])) r--;
    35             que[++r]=i;
    36         }
    37         printf("%I64d
    ",dp[n]);
    38     }
    39     return 0;
    40 }
  • 相关阅读:
    求集合的子集总结及案例
    静态资源(JS/CSS)存储在localStorage
    js 数组&字符串 去重
    跨域iframe高度计算
    Xshell5连接虚拟机出现连Could not connect to '192.168.47.128' (port 22): Connection failed,解决办法
    sql server中常用方法函数
    sql中union和union all的用法
    python(1) -文件操作
    python(1)
    python(1)
  • 原文地址:https://www.cnblogs.com/tsw123/p/4412195.html
Copyright © 2011-2022 走看看