【题目描述】

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

【题目链接】

    http://noi.openjudge.cn/ch0206/7624/

【算法】

  1. 定义dp[i][j]为前i个村庄建j个小学,构建状态转移方程为dp[i][j] = min(dp[i][j], dp[k][j] + cost[i+1][j])  其中cost[i][j]表示第i个村庄到第j个村庄建一个小学的最短距离和
  2. 预处理cost数组,众所周知,满足最短距离和的小学应该建在中位数的村庄处,同时也满足递推关系:cost[i][j] = cost[i][j-1] + dist[j] - dist[i+j>>1]
  3. 前缀和就是村庄所处位置

【代码】

  

#include <iostream>
#include <stdlib.h>
#include <algorithm>
#include <cstring>
using namespace std;
int m,n,i,j,k;
int dist[],cost[][],dp[][];
int main()
{
cin>>m>>n;
dist[]=;
for(i=;i<=m;i++)
cin>>dist[i],dist[i]+=dist[i-];
for(i=;i<=m;i++)
for(j=i+;j<=m;j++)
cost[i][j]=cost[i][j-]+dist[j]-dist[i+j>>];
memset(dp,0x7f,sizeof(dp));
for(i=;i<=m;i++) dp[i][]=cost[][i];
for(i=;i<=m;i++)
for(j=;j<=min(i,n);j++)
for(k=j-;k<i;k++)
dp[i][j]=min(dp[i][j],dp[k][j-]+cost[k+][i]);
cout<<dp[m][n];
return ;
}

最新文章

  1. js中数组去除重复项目
  2. java.sql.SQLException: JZ00L
  3. 【Swift学习】Swift编程之旅(一)
  4. 【Openlayers3】在地图上添加highcharts图表
  5. Python中的两种列表
  6. 【Mysql】安装 mysql-5.7.5 指南
  7. Android弹性ScrollView
  8. javascript模拟html title
  9. mssql执行计划查看的一些知识
  10. java的System.getProperty()获取的值
  11. 《探索未知种族之osg类生物》目录
  12. Kali学习笔记34:配置TFTP和FTP服务
  13. Golang两种执行流程以及区别
  14. centos7 关闭 防火墙
  15. apache2.2+php5.3+mysql5.5+Zend Guard Loader集成包
  16. vim复制粘贴常用命令
  17. Oracle数据库常用监控语句
  18. Prometheus 普罗米修斯监控
  19. require.js使用baseUrl + paths导入文件配置的3种方法
  20. Java ArrayList的模拟实现

热门文章

  1. MySQL导出和导入
  2. Centos 6.4 x86_64 最小化安装后的优化——还需要整理
  3. vue 常见错的可能原因
  4. 【leetcode】1143. Longest Common Subsequence
  5. react native 实现TODO APP
  6. Logstash介绍及Input插件介绍
  7. 【PowerOJ1753&amp;网络流24题】分配问题(KM)
  8. Coffee Chicken
  9. JDBC之Statement 接口的测试(存在sql注入风险)
  10. CentOS7 日常操作 2