zoukankan      html  css  js  c++  java
  • POJ 1160 Post Office(DP+经典预处理)

    题目链接:http://poj.org/problem?id=1160

    题目大意:在v个村庄中建立p个邮局,求所有村庄到它最近的邮局的距离和,村庄在一条直线上,邮局建在村庄上。

    解题思路:设dp[i][j]表示到第i个村庄为止建立j个邮局的最小距离和,dis[i][j]表示i~j之间建一个邮局的最小距离和,我们很容易得出状态转移方程:dp[i][j]=min{dp[k][j]+dis[k+1][i]}(k<i)。

         主要是dis[i][j]的预处理很巧妙,从别人的博客上看的“将邮局建在i~j中间即(i+j)/2的位置,如果i+j不能被整除建在左边和右边结果一样”。于是dis[i][j]=dis[i][j-1]+pos[j]-pos[(i+j)/2]。

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 const int N=1e3+5;
     6 
     7 int dp[N][50],pos[N],dis[N][N];//dis[i][j]表示在i~j之间建一个邮局的最小距离和 
     8 
     9 int main(){
    10     int n,m;
    11     while(~scanf("%d%d",&n,&m)){
    12         memset(dp,0x3f,sizeof(dp));
    13         for(int i=1;i<=n;i++){
    14             scanf("%d",&pos[i]);
    15         }
    16         //预处理dis[i][j]
    17         for(int i=1;i<=n;i++){
    18             dis[i][i]=0;
    19             for(int j=i+1;j<=n;j++){
    20                 dis[i][j]=dis[i][j-1]+pos[j]-pos[(i+j)/2];
    21             }
    22             dp[i][1]=dis[1][i];
    23         }
    24         
    25         for(int j=2;j<=m;j++){
    26             for(int i=j;i<=n;i++){
    27                 for(int k=j-1;k<i;k++){
    28                     dp[i][j]=min(dp[k][j-1]+dis[k+1][i],dp[i][j]);
    29                 }
    30             }
    31         }
    32         printf("%d
    ",dp[n][m]);
    33     }
    34     return 0;
    35 }
  • 相关阅读:
    bzoj 4260REBXOR
    bzoj 1009GT考试
    cf 621E. Wet Shark and Blocks
    cf 507E. Breaking Good
    cf 766#
    bzoj 3732Network
    bzoj 4300绝世好题
    bzoj 4345[POI2016]Korale
    bzoj 4236JOIOJI
    bzoj 4237稻草人
  • 原文地址:https://www.cnblogs.com/fu3638/p/7827702.html
Copyright © 2011-2022 走看看