• HDU 2829 Lawrence(斜率优化DP O(n^2))


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2829

    题目大意:有一段铁路有n个站,每个站可以往其他站运送粮草,现在要炸掉m条路使得粮草补给最小,粮草补给的公式是将每个站能收到的粮草的总和。

    4----5-----1-----2

    粮草总和为4*5 + 4*1 + 4*2 + 5*1 + 5*2 + 1*2 = 49.

    4----5       1-----2

    粮草总和为4*5 + 1*2 = 22. 

    4      5-----1------2

    粮草总和为5*1 + 5*2 + 1*2 = 17.

    解题思路:数组dp[i][j]表示第i个位置炸成j段的最小价值,cost[i][j]表示i~j这段的价值,则得到状态转移方程:

         dp[i][j]=min{dp[k][j-1]+cost[k+1][i]}.(k<i),复杂度为O(n^3)显然会超时

         易得cost[1][i]=cost[1][k]+cost[k+1][i]+sum[k]*(sum[i]-sum[k])

         则cost[k+1][i]=cost[1][i]-cost[1][k]+sum[k]^2-sum[k]*sum[i].

         使用cost[i]表示cost[1][i]得,dp[i][j]=min{dp[k][j-1]+cost[i]-cost[k]+sum[k]^2-sum[k]*sum[i]}.   

         可以得出 y=dp[k][j-1]-cost[1][k]+sum[k]^2

         x=sum[k].

         斜率sum[i]。

         用斜率优化,将复杂度降为O(n^2)即可。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=1e3+5;
     6 int dp[N][N],sum[N],cost[N],q[N],head,tail;
     7 
     8 //yj-yk/xj-xk 
     9 double Slope(int m,int k,int j){
    10     return double(dp[j][m-1]+sum[j]*sum[j]-cost[j]-dp[k][m-1]-sum[k]*sum[k]+cost[k])/(sum[j]-sum[k]);
    11 }
    12 
    13 //dp[i][j]=min{dp[k][j-1]+cost[i]-cost[k]-sum[k]*(sum[i]-sum[k])} 
    14 int getDP(int i,int j,int k){
    15     return dp[k][j-1]+cost[i]-cost[k]-sum[k]*(sum[i]-sum[k]);
    16 }
    17 
    18 int main(){
    19     int n,m;
    20     while(~scanf("%d%d",&n,&m)){
    21         if(m==0&&n==0)
    22             break;
    23         memset(cost,0,sizeof(cost));
    24         sum[0]=0;
    25         for(int i=1;i<=n;i++){
    26             scanf("%d",&sum[i]);
    27             sum[i]+=sum[i-1];
    28         }
    29         for(int i=1;i<=n;i++){
    30             for(int j=1;j<i;j++){
    31                 cost[i]+=(sum[j]-sum[j-1])*(sum[i]-sum[j]);
    32             }
    33             dp[i][1]=cost[i];
    34         }
    35         for(int j=2;j<=m+1;j++){
    36             head=tail=0;
    37             q[tail++]=j-1;
    38             for(int i=j;i<=n;i++){
    39                 while(head+1<tail&&Slope(j,q[head],q[head+1])<=sum[i]){            
    40                     head++;
    41                 }
    42                 dp[i][j]=getDP(i,j,q[head]);
    43                 while(head+1<tail&&Slope(j,q[tail-2],q[tail-1])>=Slope(j,q[tail-1],i)){
    44                     tail--;
    45                 }
    46                 q[tail++]=i;        
    47             }
    48         }
    49         printf("%d
    ",dp[n][m+1]);
    50     }
    51     return 0;
    52 }

         

  • 相关阅读:
    面试题三:MySQL
    面试题二:JVM
    面试题一:类加载
    RabbitMq脑裂问题
    数据结构之树学习内容
    JVM全面分析之垃圾收集器
    JVM全面分析之垃圾回收的相关概念
    JVM全面分析之垃圾回收算法
    JVM全面分析之String
    JVM全面分析之执行引擎
  • 原文地址:https://www.cnblogs.com/fu3638/p/7815072.html
Copyright © 2020-2023  润新知