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...
原文地址:https://www.cnblogs.com/xxx0624/p/3040913.html