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         

 

你可能感兴趣的:(HDU)