题目:
描述
政府在某山区修建了一条道路,恰好穿越总共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


所属专栏:戳我访问

山区建小学不是《信息学奥赛一本通第5版》的例题,是noi官方题库的题目。
这题用动态规划来解决,这里需要一个辅助的数组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]);

状态数量:n^2
转移代价:O(n)
时间复杂度:O(n^3)
空间复杂度:O(n^2)(忽略常数)
分析完毕。
还有一点,就是有关如何求dist数组的,其实,我们可以发现,在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;
}

动态规划——openjudge7624山区建小学相关推荐

  1. 【披着递推皮的动态规划】 山区建小学 题解

    今天小编随意写了一道老师布置的题,这是一道看起来很普通的题,我却不明白它为什么放在递推中-- 废话不多说,直接看题. ▍1197:山区建小学 [题目描述] 政府在某山区修建了一条道路,恰好穿越总共m个 ...

  2. 信息学奥赛一本通(1197:山区建小学)

    1197:山区建小学 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 3900     通过数: 2713 [题目描述] 政府在某山区修建了一条道路,恰好穿越总共m ...

  3. 1197 山区建小学

    1197 山区建小学 读题20分钟,想题10分钟,看代码20分钟,理解代码20分钟,写代码10分钟,调代码40分钟-(逃 个人感觉是练的递推里面比较复杂的,应该是一道绿题吧,光递推式就很难找 设状态a ...

  4. 【Open Judge】7624 山区建小学

    ** 7624:山区建小学 ** ** 描述 ** 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为d ...

  5. 山区建小学 动态规划

    描述 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往. 已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i &l ...

  6. openjudge7624:山区建小学

    描述 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < ...

  7. 7624:山区建小学

    题目链接 描述 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < ...

  8. 【OpenJudge - noi - 7624】山区建小学(dp)

    题干: 总时间限制: 1000ms 内存限制: 65536kB 描述 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的 ...

  9. 山区建小学(信息学奥赛一本通-T1197)

    [题目描述] 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为didi(为正整数),其中,0<i ...

最新文章

  1. Python 第十五天 串讲
  2. Clojure世界:单元测试
  3. 初探目前最火的鸿蒙系统,跑了个 “hello world”!
  4. 软件开发中IT用语-日文和英文对照版
  5. java项目中的classpath
  6. JavaWeb:tomcat服务器安装总结及Http协议
  7. java md5 密钥_Java 生成16/32位 MD5密钥串
  8. OsharpNS轻量级.net core快速开发框架简明入门教程-基于Osharp实现自己的业务功能...
  9. [转]SSAS没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG)) (Microsoft Visual Studio)的解决办法...
  10. [Error]Python虚拟环境报错 OSError: setuptools pip wheel failed with error code 2
  11. [译]简单声明Lua类
  12. 跟我一起来用C++写Web服务器吧
  13. resultset java 类型_java 中的resultset的类型
  14. 安装tensorflow出现的问题
  15. 图论及其应用 2012年 期末考试答案总结
  16. 阿里云 mysql yum源_安装阿里云yum源
  17. cavas的验证码效果demo
  18. win7系统wifi没有网络连接到服务器,Win7旗舰版没有无线网络连接怎么办?
  19. 二层、三层与四层交换机
  20. html上绑定回车事件,js/jquery中input 绑定回车enter事件的代码

热门文章

  1. 计算机阅卷系统 流程,中考电脑阅卷流程参考.pdf
  2. 弹性力学偏微分方程组及其边界条件
  3. 综合项目:人工智能领域目前职位及薪资现状分析 - 基于主流招聘网站信息
  4. 正确实现AutoCAD布局打印过程详解
  5. 数码相机的闪光灯使用经验
  6. 从入门到迷糊:戏谈和吐槽即将到来的5G移动通信技术(以及历代)的各种简称
  7. 渗透测试用工具(三)layer子域名挖掘机
  8. 港湾设备石油设施锅炉地埋用无机富锌防腐底漆 漆膜干燥较快
  9. linux_CentOS重启网络命令
  10. android模拟全局按键,Android 模拟按键汇总