zoukankan      html  css  js  c++  java
  • HDU3507+DP斜率优化

    详见http://www.cnblogs.com/xiaolongchase/archive/2012/02/10/2344769.html

    View Code
     1 /*
     2 dp+斜率优化
     3 题意:给定一些点,把这些点分成某些行
     4 对于分成同一行的点的代价为:( sigma(x)*sigma(x)+m )
     5 求最小的代价
     6 dp[ i ] = min( dp[ j ]+(sum[i]-sum[j])^2+m )  (其中j<=i)//以第i个点为末尾的最小代价
     7 
     8 首先对于任意的j,k( j<k<=i )
     9 如果说k的决策由于j,那么可得到dp[ k ]+(sum[i]-sum[k])^2+m<dp[j]+(sum[i]-sum[j])^2+m
    10 移项可得 { dp[j]+sum[j]^2-(dp[k]+sum(k)^2) }/( sum[j]-sum[k] ) < 2*sum[i];
    11 再令 solve( j,k ) = { dp[j]+sum[j]^2-(dp[k]+sum(k)^2) }/( sum[j]-sum[k] );
    12 那么也就是说如果决策 k 优于决策 j ,就能得到 solve( j,k )<2*sum[i]; 
    13 ->->->->->->->这就是结论1
    14 
    15 对于任意的 j,k,p ( j<k<p ),有solve( j,k ),solve( k,p );
    16 IF( solve( j,k )>solve( k,p ) ) {
    17     if( solve( k,p )<2*sum[i] ) p优于k,则k是无用的决策
    18     if( solve( k,p )>2*sum[i] ) 能推出solve( j,k )>2*sum[i],也就是说k不比j优,同样的k是无用的决策,可以去掉
    19     so,只要满足这个大的IF条件,那么k就是无用的决策
    20 
    21 */
    22 #include<stdio.h>
    23 #include<string.h>
    24 typedef long long int64;
    25 const int maxn = 500005;
    26 const int inf = 99999999;
    27 
    28 int64 sum[ maxn ];
    29 int64 dp[ maxn ];
    30 int que[ maxn ];
    31 
    32 int solve( int j,int k ){
    33     if( sum[j]==sum[k] ){//防止除0
    34         if( dp[j]>dp[k] ) return -1;//这个要由最原始的solve推出
    35         else return inf;
    36     }
    37     return (dp[j]-dp[k]+sum[j]*sum[j]-sum[k]*sum[k])/(sum[j]-sum[k]);
    38 }
    39 
    40 int main(){
    41     int n,m;
    42     while( scanf("%d%d",&n,&m)!=EOF ){
    43         memset( dp,0,sizeof( dp ) );
    44         //memset( que,0,sizeof( que ));
    45         sum[ 0 ] = 0;
    46         for( int i=1;i<=n;i++ ){
    47             scanf("%lld",&sum[i]);
    48             sum[i] += sum[i-1];
    49         }
    50         int head,tail;
    51         head = tail = 0;
    52         for( int i=1;i<=n;i++ ){
    53             while( head<tail && solve( que[ head ],que[ head+1 ] )<2*sum[i] )
    54                 head++;
    55                 //结论1
    56             dp[ i ] = dp[ que[ head ] ]+(sum[que[head]]-sum[i])*(sum[que[head]]-sum[i])+m;
    57             while( head<tail && solve( que[ tail-1 ],que[ tail ] )>solve( que[ tail ],i ) )
    58                 tail--;
    59                 //结论2
    60             tail++;
    61             que[ tail ] = i;
    62         }
    63         printf("%lld\n",dp[n]);
    64     }
    65     return 0;
    66 }
    67         
    keep moving...
  • 相关阅读:
    XP系统忘记密码解决方法
    实现一个简易的IoC框架(上)(此篇与Spring.NET无关,为自己手写IoC框架)
    Spring.NET教程(三)——对象的创建(基础篇)
    Spring.NET教程(二)——环境搭建(基础篇)
    Spring.NET教程(一)——控制反转(依赖注入)(基础篇)(转)
    递归与迭代
    软件研发人员考核的十项基本原则(转)
    ORACLE多表关联的update语句
    软件质量的分层控制方法
    技术研究与工程开发(转)
  • 原文地址:https://www.cnblogs.com/xxx0624/p/3040913.html
Copyright © 2011-2022 走看看