#DP# ----- OpenJudge山区建小学
没有记性。到DP不得不写博了,三天后又忘的干干净净。DP是啥 :-)
一道久到不能再久的题了。
OpenJudge 7624:山区建小学
- 总时间限制: 1000ms 内存限制: 65536kB
- 描述
-
政府在某山区修建了一条道路,恰好穿越总共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 因为所求为距离和最小,所以发现选择一个点a建立学校后,以a为中心向两边扩散下一个点所走的距离d=d(前一个点)+d(当前);期望重复次数越多路段d越小。然后,就有dalao证明了区间[i,j]中在中点处建学校路段和为最小(建1所学校);脑洞又开到:如果区间内点数为偶数,如何选择中点?手推数据发现其实都是一样的。在此计算的为距离和,所以实则计算的是 d总+=di*重复次数。如图:

考虑DP:从第一个村庄开始扩展,在区间[1,i],每加入一个点i进行决策 。
状态转移方程:f[i][j]=min(f[i][j],f[k][j-1]+w[k+1][i]);
f[i][j] 表示到第i个点建j所学校的最优;在区间[1.i]间枚举断点,断点前为在区间[1,k]建j-1所学校的最优,断点后为在区间[k+1,i]建1所学校的最优。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std; int n,m;
int d[][],f[][],w[][],s[]; int pre(int a,int b){
int x=;
int mid=(a+b)>>;
for(int i=a;i<=b;++i)
x+=d[i][mid];
return x;
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i){//s[i]---第i-1个村庄到第i个村庄间的距离
int x;
scanf("%d",&x);
s[i]=s[i-]+x;
}
memset(f,0x3f3f3f,sizeof(f));
for(int i=;i<=n;++i){
f[i][i]=;
for(int j=;j<=n;++j){
if(i==j)d[i][j]=;
d[i][j]=d[j][i]=abs(s[i]-s[j]);//(i,j)间的距离
}
}
for(int i=;i<=n;++i)//(i,j)建1所小学min
for(int j=i+;j<=n;++j)
w[i][j]=pre(i,j);
for(int i=;i<=n;++i)f[i][]=w[][i];
for(int i=;i<=n;++i)// 村庄
for(int j=;j<=min(i,m);++j)//j---学校 min(枚举的村庄数,学校数)
for(int k=j-;k<i;++k)//min( f[i][j],建j-1所学校所达范围(1,k)+新建第j所学校范围(k+1,i))
if(i!=j)f[i][j]=min(f[i][j],f[k][j-]+w[k+][i]); printf("%d",f[n][m]);
return ;
}
#DP# ----- OpenJudge山区建小学的更多相关文章
- 【OpenJudge7624】【区间DP】山区建小学
山区建小学 总时间限制: 1000ms 内存限制: 65536kB [描述] 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两 ...
- 山区建小学(区间DP)
山区建小学 时间限制: 1 Sec 内存限制: 128 MB提交: 17 解决: 5[提交][状态][讨论版][命题人:quanxing] 题目描述 政府在某山区修建了一条道路,恰好穿越总共m个村 ...
- P4677 山区建小学|区间dp
P4677 山区建小学 题目描述 政府在某山区修建了一条道路,恰好穿越总共nn个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di 为了提高山区 ...
- 7624:山区建小学(划分dp)
7624:山区建小学 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄 ...
- NOI题库7624 山区建小学(162:Post Office / IOI2000 POST OFFICE [input] )
7624:山区建小学 Description 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di(为 ...
- 山区建小学(区间dp+前缀和+预处理)
[题目描述] 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i ...
- OpenJudge 7624 山区建小学
在openjudge似乎无法凭题号搜到题...? 总时间限制: 1000ms 内存限制: 65536kB 描述 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任 ...
- luogu P4677 山区建小学 |dp
题目描述 政府在某山区修建了一条道路,恰好穿越总共nnn个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为did_idi(为正整数),其中,0& ...
- Openjudge — 7624 山区建小学
问题描述 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i & ...
随机推荐
- DEDECMS模板中dede标签使用php和if判断语句的方法
先来看看下面这个标签{dede:field.tong_gg php=yes}if(@me==""||empty(@me))@me="<p>无</p> ...
- iframe载入等待
<style> #pageloading{position:absolute; left:0px; top:0px;background:white url('../images/load ...
- Mysql基于GTID主从复制
Mysql5.6基于GTID全局事务的复制 什么是GTID? GTID(Global Transaction Identifiers)是全局事务标识 当使用GTIDS时,在主上提交的每一个事务都会 ...
- objective-c学习笔记2
Objective-c学习笔记 1.cocoa的对象初始化一般使用alloc和init两个方法,不适用new,其中alloc用于分配内存,init用于初始化,因为初始化方法返回的对象可能和分配的对象不 ...
- HTML学习二(基础)
HTML标题标题(Heading)是通过<h1>-<h6>等标签进行定义的<h1>定义最大标题<h6>定义最小标题注释:浏览器会自动地在标题的前后添加空 ...
- CKeditor使用js验证不得为空
if (CKEDITOR.instances.TextArea1.getData() == '') { alert('警告:详细内容不得为空!'); CKEDITOR.instances.TextAr ...
- Thinking in scala (8)---- 乘幂计算
递归的方式: b^n = (b^(n/2))^2 若n是偶数 b^n = b*(b^(n-1)) 若n是奇数 迭代的方式 product:存储中间结果,初始化为1 b^n = (b^2)^(n/2) ...
- 详解Objective-C的meta-class 分类: ios相关 ios技术 2015-03-07 15:41 51人阅读 评论(0) 收藏
比较简单的一篇英文,重点是讲解meta-class.翻译下,加深理解. 原文标题:What is a meta-class in Objective-C? 原文地址:http://www.cocoaw ...
- lua 函数
1.函数只有一个参数,且该参数为table 或 字符串时,调用函数可以省略() print"hello world" 同 print("hello world" ...
- IOS开发-UI学习-NSBundle和NSURL的区别(读取文件以及写入文件)
NSBundle和NSURL的区别: 在项目的工程中添加一个文件,本例程添加的是aa.txt,文件的内容为百度: www.baidu.com,现在要使用NSBundle和NSURL分别去获取内容,代码 ...