zoukankan      html  css  js  c++  java
  • poj1160

       题目大意:在一个一维坐标轴上有v个(1<=v<=300)村庄,要建p(1<=p<=30)个邮局,每个村庄都到最近的邮局,要求最小的距离和。

         四边形不等式,据说黑书上写得很高深。

       描述是这样的:令(a<=b<=c<=d,i<=k<j),若w[a][c]+w[b][d]<=w[a][d]+w[b][c],m[i][j]=min OR max{m[i][k]+m[k+1][j]+w[i][j]}则m[a][c]+m[b][d]<=m[a][d]+m[b][c]。

       对于这个式子,个人觉得没必要深究,读者读读题目就应该知道自己要求的m[i][j]定义,取min或者max。我也不会证明,只能弱弱感受到是这么回事。(毕竟那些都不重要,因为不涉及最后求解结果)

         最重要的是这个式子,假设s[i][j]是对应取到m[i][j]的最优解(s当然是solution的意思了,关于解的描述要细细考虑,因为它并不用是一种很确切的表示,只需要是一个关键的量就可以)。PS:我觉得,我要是不解释这个关键量,很多人肯定会黑我的,但是我真的不知道怎么表达。看代码中的注解吧。

        四边形不等式最大优化是s[i][j]一定介于s[k=i-1 或者 k=i+1][j]、s[i][j+1]之间。(也有很多博客上写成s[i-1][j]<=s[i][j]<=s[i][j+1])这样对于我们搜索关于s[i][j]的值时范围大大缩短了。对于s[i][max_(i)]可以用我们通常容易想到的dp方程线性效率解决。而s[i][1]到s[i][max_(i)-1]这一段的解,总共的效率可以缩短到线性。 

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 const int infinity=(-1)^(1<<31);
     7 const int V=305;
     8 const int P=35;
     9 int dp[V][P], s[V][P];
    10 int atx[V],sum[V];
    11 inline int setat(int i,int j){
    12     return (i+j)>>1;
    13 }
    14 int move_all(int fr,int ba){
    15     //printf("move from %d to %d = %d
    ",fr,ba,(sum[ba]-sum[fr])-atx[fr]*(ba-fr));
    16     return (sum[ba]-sum[fr])-atx[fr]*(ba-fr);
    17 }
    18 int S(int i,int j){
    19     int pos=setat(i,j);
    20     int ret=move_all(pos,j);
    21     ret += (atx[pos]-atx[i])*(pos-i+1)-move_all(i,pos);
    22     return ret;
    23 }
    24 int DP(int v,int p){
    25     sort(atx+1,atx+1+v);
    26     for(int i=v;i>=1;i--) atx[i]-=atx[1];
    27     for(int i=1;i<=v;i++) sum[i]=sum[i-1]+atx[i];
    28     //for(int i=1;i<=v;i++) printf("%3d ",atx[i]); printf("
    ");
    29     for(int i=1;i<=v;i++)
    30         dp[i][1]=S(1,i), s[i][1]=setat(1,i); //printf("1 --> %4d, %d
    ",i,dp[i][1]);
    31     if(p >= 2)
    32     for(int i=2;i<=v;i++){
    33         int maxj=min(i,p);
    34         dp[i][maxj]=infinity;
    35         for(int k=maxj-1;k<i;k++)
    36         if(dp[k][maxj-1]+S(k+1,i) < dp[i][maxj])
    37             dp[i][maxj]=dp[k][maxj-1]+S(k+1,i), s[i][maxj]=k;
    38         //printf("dp[%d][%d] = %d, s[i][maxj] = %d
    ",i,maxj,dp[i][maxj],s[i][maxj]);
    39         for(int j=maxj-1;j>=2;j--){
    40             dp[i][j]=infinity;
    41             for(int k=s[i-1][j];k<=s[i][j+1];k++)
    42             if(dp[k][j-1]+S(k+1,i) < dp[i][j]){
    43                 dp[i][j]=dp[k][j-1]+S(k+1,i);
    44                 s[i][j]=k;
    45             }
    46         }
    47     }
    48     return dp[v][p];
    49 }
    50 int main()
    51 {
    52     int v,p;
    53     while(scanf("%d%d",&v,&p) != EOF){
    54         for(int i=1;i<=v;i++)
    55             scanf("%d",&atx[i]);
    56         printf("%d
    ",DP(v,p));
    57     }
    58     return 0;
    59 }
    View Code

      个人觉得,在很多性质上,它跟斜率优化dp很像,甚至可以说斜率优化dp是最特殊的一类四边形不等式dp。斜率优化的dp中,最优化只根一个值有关,因为它保持后来无关单调。四边形不等式,把最优解的可选方案限制起来。

      我也是四边形不等式的初学者,希望路过的大牛不吝赐教。

  • 相关阅读:
    openwrt 相关文章
    负载均衡相关文章
    Today's Progress
    Rodrigues formula is beautiful, but uneven to sine and cosine. (zz Berkeley's Page)
    Camera Calibration in detail
    Fundamental Matrix in Epipolar
    Camera Calibration's fx and fy do Cares in SLAM
    FilterEngine::apply
    FilterEngine 类解析——OpenCV图像滤波核心引擎(zz)
    gaussBlur
  • 原文地址:https://www.cnblogs.com/karlvin/p/3330896.html
Copyright © 2011-2022 走看看