zoukankan      html  css  js  c++  java
  • Openjudge — 7624 山区建小学

    ###问题描述### 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < m。为了提高山区的文化素质,政府又决定从m个村中选择n个村建小学(设 0 < n < = m < 500 )。请根据给定的m、n以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值。 ###输入### 第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。 ###输出### 各村庄到最近学校的距离之和的最小值。 ###样例输入### 10 2 3 1 3 1 1 1 1 1 3 ###样例输出### 18 来源 元培-From Whf

    ###解题思路:### 动态规划来解决,这里需要一个辅助的数组dist,dist[i][j]表示在从i到j这一段区间建一所小学,i到j的村庄都到这个学校来上学的路程和。 状态表达:f[i][j]表示前i个村庄建j所学校,到里那个村庄最近的学校上学的路程和。 状态转移:f[i][j] = std::min(f[i][j],f[k][j-1]+dist[k+1][i]),也就是:

    for(int i = 1;i<=n;i++)
            for(int j = 1;j<i;j++)
                for(int k = 1;k<i;k++)
                    f[i][j] = std::min(f[i][j],f[k][j-1]+dist[k+1][i]);   
    

    状态数量:n2 转移代价:O(n) 时间复杂度:O(n3) 空间复杂度:O(n^2)

    还有一个关键点,就是有关如何求dist数组的,其实,我们可以发现,在i到j村庄里建小学,选i到j村庄的路程的中间位置村庄,一定是最优的。画个图你就能发现了。 如何快速求dist呢,其实,dist[i][j]等于dist[i][j-1]+num[j]-num[i+j]/2的,建议画个图。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    
    int num[1001],dist[1001][1001],f[1001][1001];
    int main()
    {
        int n,m;
        std::cin>>n>>m;
        for(int i = 2;i<=n;i++){std::cin>>num[i];num[i] += num[i-1];}
        for(int i = 1;i<=n;i++)
            for(int j = i;j<=n;j++)
                dist[i][j] = dist[i][j-1]+num[j]-num[(i+j)/2];
        memset(f,0x3f,sizeof(f));
        for(int i = 1;i<=n;i++)f[i][1] = dist[1][i];
        for(int i = 1;i<=n;i++)
            for(int j = 1;j<i;j++)
                for(int k = 1;k<i;k++)
                    f[i][j] = std::min(f[i][j],f[k][j-1]+dist[k+1][i]);
        std::cout<<f[n][m];
        return 0;
    }
    
  • 相关阅读:
    python字符串
    Python问题:SyntaxError: Non-ASCII character 'xe2' in file
    windows 运行库与dll文件
    sublime python 配置内容
    sublime ctrl b突然不能用解决方法
    c++ primer 的 textquery 例子。
    虚函数表
    理解各种数据类型和简单类在内存中的存在形式。
    最短路径纯贪心算法。
    中缀表达式生成二叉树
  • 原文地址:https://www.cnblogs.com/tham/p/10037360.html
Copyright © 2011-2022 走看看