P4677 山区建小学题解
P4677 山区建小学
题目描述
政府在某山区修建了一条道路,恰好穿越总共 nnn 个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村庄之间的距离为 did_idi(did_idi 为正整数),其中,0<i<n0<i<n0<i<n。为了提高山区的文化素质,政府又决定从 nnn 个村中选择 mmm 个村建小学。请根据给定的 nnn、mmm 以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值。
输入格式
第一行为 nnn 和 mmm,其间用空格间隔。
第二行为 n−1n-1n−1 个整数,依次表示从一端到另一端的相邻村庄的距离,整数之间以空格间隔。
例如
10 3
2 4 6 5 2 4 3 1 3
表示在 101010 个村庄中建 333 所学校。第 111 个村庄与第 222 个村庄距离为 222,第 222 个村庄与第 333 个村庄距离为 444,第 333 个村庄与第 444 个村庄距离为 666,…,第 999 个村庄到第 101010 个村庄的距离为 333。
输出格式
各村庄到最近学校的距离之和的最小值。
输入输出样例 #1
输入 #1
10 2
3 1 3 1 1 1 1 1 3
输出 #1
18
说明/提示
1≤m≤n<5001 \le m \le n < 5001≤m≤n<500,1≤di≤1001 \le d_i \le 1001≤di≤100。
思路
直接区间DP即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long n,m,a[100005],b[100005],b2[100005],b3[100005],f[505][505],db=0,op=1e18+7;
int main(){
cin>>n>>m;
for(int i=2;i<=n;i++){
cin>>a[i];
b[i]=b[i-1]+a[i];
}
memset(f,62,sizeof(f));
for(int i=1;i<=n;i++){
db=0;
for(int j=1;j<=i;j++){
db+=(b[i]-b[j]);
}
f[i][1]=db;
for(int k=1;k<=i-1;k++){
db=0;
for(int j=k;j<=i;j++){
db+=min(b[j]-b[k],b[i]-b[j]);
}
for(int j=2;j<=m;j++){
f[i][j]=min(f[i][j],f[k][j-1]+db);
}
}
}
for(int i=1;i<=n;i++){
db=0;
for(int j=i;j<=n;j++){
db+=(b[j]-b[i]);
}
op=min(op,f[i][m]+db);
}
cout<<op<<endl;
return 0;
}

浙公网安备 33010602011771号