NOI题库7624 山区建小学

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)<<"\n";
48
49     return 0;
50 }
时间: 2024-12-08 10:18:43

NOI题库7624 山区建小学的相关文章

NOI 题库 7624

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

7624:山区建小学

7624:山区建小学 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < m.为了提高山区的文化素质,政府又决定从m个村中选择n个村建小学(设 0 < n < = m < 500 ).请根据给定的m.n以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村

openjudge 7624:山区建小学

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

【noi 2.6_7624】山区建小学(DP)

题意:在m个村庄建n个小学,求所有村到最近小学的距离总的最小值. 解法:由于题目是求“离最近的学校”,而不是前一个学校,所以枚举学校的具体位置不方便,可转化成区间(学校居区间中间)的划分问题. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 5 const int N=510,M=510; 6 int a[N],s[N],f[N][M],dis[N][N]; 7 8 int mmin(int x,

ybt1197;p4677 山区建小学(博客里第一道蓝题)

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

[NOI题库]1.1题解

今年NOIP居然"各有两道题目从NOI题库中抽取并在原题基础上改动后使用",不好好刷题怎么行. 这是第一篇题解文章,因为题目太水直接上代码了. 1.1编程基础之输入输出 01 Hello, World! 根据题意直接输出"Hello, World!"即可. #include <iostream> using namespace std; int main() { cout<<"Hello, World!"<<e

NOI题库 1768最大子矩阵 题解

NOI题库 1768最大子矩阵  题解 总时间限制: 1000ms 内存限制: 65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 的最大子矩阵是 9 2 -4 1 -1 8 这个子矩阵的大小是15. 输入   输入是一个N * N的矩阵.输入的第一行给出N (0 < N <= 100).再后面的若干行中,依

P4677 山区建小学|区间dp

P4677 山区建小学 题目描述 政府在某山区修建了一条道路,恰好穿越总共nn个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di 为了提高山区的文化素质,政府又决定从n个村中选择m个村建小学. 请根据给定的n.m以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值. 题解:https://www.luogu.org/blog/hsfzLZH1/solution-p4677 区间dp主要是下面这几段

山区建小学(区间型动态规划,递推)

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