• NOI题库7624 山区建小学(162:Post Office / IOI2000 POST OFFICE [input] )


    7624:山区建小学

    Description

    政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < m。为了提高山区的文化素质,政府又决定从m个村中选择n个村建小学(设 0 < n < = m < 500 )。请根据给定的m、n以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值。

    Input

    第1行为m和n,其间用空格间隔
    第2行为(m-1) 个整数,依次表示从一端到另一端的相邻村庄的距离,整数之间以空格间隔。

    例如
    10 3
    2 4 6 5 2 4 3 1 3
    表示在10个村庄建3所学校。第1个村庄与第2个村庄距离为2,第2个村庄与第3个村庄距离为4,第3个村庄与第4个村庄距离为6,...,第9个村庄到第10个村庄的距离为3。

    Output

    各村庄到最近学校的距离之和的最小值。

    Sample Input

    10 2

    3 1 3 1 1 1 1 1 3

    Sample Output

    18

    【思路】

       划分型DP。

       首先对于ij区间,将学校建在中点位置距离区间内的点最短。

       设d[i][j]表示前i个村庄建j所学校的最短距离。则有转移式:

         d[i][j]=min{ d[k][j-1]+cost(k+1,i) }  (j-1<= k <i)

       转移式表示在区间k+1..i的中点建立一所学校使这个区间内的所有村庄都到这里上学,其中cost为最小距离之和。

    【代码】

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cmath>
     4 using namespace std;
     5 
     6 const int maxn = 500+10;
     7 const int INF=0x3f3f3f3f;
     8 
     9 int d[maxn][maxn];
    10 int sum[maxn];
    11 int cost[maxn][maxn];
    12 int n,m;
    13 
    14 void get_cost()
    15 {
    16     for(int i=1;i<=n;i++)
    17        for(int j=i;j<=n;j++)
    18         {
    19             cost[i][j]=0;
    20             int mid=i+(j-i)/2;
    21             for(int k=i;k<=j;k++) cost[i][j] += abs(sum[mid]-sum[k]);
    22         }
    23 }
    24 
    25 int dp(int i,int j)
    26 {
    27     int &ans=d[i][j];
    28     if(ans<INF) return ans;
    29     
    30     if(i<j) return INF;
    31     if(i==j) return ans=0;       //i==j
    32     if(j==1) return ans=cost[1][i]; //cost(1,i)
    33     
    34     for(int k=j-1;k<i;k++)
    35        ans=min(ans,dp(k,j-1)+cost[k+1][i]);
    36     return ans;
    37 }
    38 
    39 int main() {
    40     ios::sync_with_stdio(false);
    41     cin>>n>>m;
    42     for(int i=2;i<=n;i++) cin>>sum[i] , sum[i] += sum[i-1]; 
    43     
    44     get_cost();
    45 
    46     memset(d,0x3f,sizeof(d));
    47     cout<<dp(n,m)<<"
    ";
    48     
    49     return 0;
    50 }
  • 相关阅读:
    C:把算术表达式分成Token
    JavaScript数据结构——链表的实现与应用
    JavaScript数据结构——队列的实现与应用
    JavaScript数据结构——栈的实现与应用
    由“RangeError: Invalid status code: 0”错误所引发的思考
    工作是最好的投资——图书摘录
    Node.js在指定的图片模板上生成二维码图片并附带底部文字说明
    苹果手机对网页上样式为position:fixed的弹窗支持不好的解决办法
    自定义react数据验证组件
    Ubuntu 18.04中截图工具Shutter的编辑按钮不可用的解决办法
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4905545.html
Copyright © 2020-2023  润新知