Time Limits: 1000 ms Memory Limits: 131072 KB Detailed Limits
Description
在 J 市的一条笔直的公路旁分布着 n 个村庄,每个村庄都有一个唯一的坐标 Xi,任意一对村庄的坐标不同。最近,J 市领导计划在村庄里新建 m 个邮局,而邮局在 n个村庄里的分布情况会影响到居民的便利程度。
设 m 个邮局分别建在 P1,P2,..,Pm 号村庄。每个村庄的村民都会找到与其距离最近的一个邮局,若有多个距离最近的则会任选一个,该村庄的便利度即为该村庄与其最近的邮局的距离,而所有村庄的便利度的和即为总便利度。
严格地讲,总便利度 C定义为
Σmin{|Xi-XPj| (1≤j≤m)}
现在,由你来安排邮局的建设位置。请计算最小的 C 是多少。
Input
第一行两个整数 n m
第二行递增的n 个整数,表示 X1..Xn
Output
一行一个整数,表示最小的 C
Sample Input
10 5 1 2 3 6 7 9 11 22 44 50
Sample Output
9
Data Constraint
对于30%的测试数据 n ≤ 10
对于60%的测试数据 n ≤ 50
对于100%的测试数据 1 ≤ n ≤ 300; 1 ≤ m ≤ 30; m ≤ n; 1 ≤ Xi ≤ 10000
Hint
样例解释:建立在坐标为:2 7 22 44 50的位置
每个村庄的便利度分别为:1 0 1 1 0 2 4 0 0 0
反思
真的要好好反思。
比赛时想到了转移和状态, 却发现不知道初值怎么赋:
f[i][0]这个状态的值应该为多少 ?
事实上吗这个状态是没有意义的。但是为了解决这个状态的值, 我还tm设了左右两个基准点, Wa是应该的。
其实预处理出f[i][1]就行了。
#include<bits/stdc++.h>
#define open(x) freopen(x".in", "r", stdin);freopen(x".out", "w", stdout)
#define mem(a, b) memset(a, b, sizeof(a))
#define mcy(a, b) memcpy(a, b, sizeof(a))
#define pf printf
#define sf scanf
#define fo(i, a, b) for( int i = a; i <= b; ++i)
#define fown(i, a, b) for( int i = a; i >= b; --i)
#define em(p, x) for(int p=tail[x];p;p=e[p].fr)
#define wt(a, c, d, s) fo(i, c, d) pf((s), a[i]); puts("")
#define rd(a, c, d) fo(iii, c, d) in((a)[i])
#define N 310
#define inf 147483647
#define maxn 10010
using namespace std;
template<class T>
T in(T &x) {
x=0;
char ch = getchar(); int f = 0;
while(ch < '0' || ch > '9') f |= ch == '-', ch = getchar();
while(ch >= '0' && ch <= '9') x = (x<<1) + (x<<3) + ch - '0', ch = getchar();
x = f ? -x : x;
return x;
}
int n, m, a[N], ans, bz[N], f[N][N], g[maxn], num[maxn];
int abss(int x) {return x < 0 ? -x : x;}
int gsum(int x, int y) {return g[y] - g[x - 1];}
int get_num(int x, int y) {return num[y] - num[x -1];}
int main() {
open("post");
in(n), in(m);
fo(i, 1, n) in(a[i]), (num[a[i]]++), (g[a[i]]+=a[i]);
sort(a + 1, a + 1 + n);
fo(i, 1, maxn) (num[i]+=num[i - 1]), (g[i]+=g[i - 1]);
ans = inf;
mem(f, 127);
fo(i, 1, n) f[i][1] = a[i] * get_num(0, a[i] - 1) - gsum(0, a[i] - 1) - a[i] * get_num(a[i] + 1, a[n]) + gsum(a[i] + 1, a[n]);
fo(i, 1, n)
{
int up = min(i, m);
fo(j, 2, up) {
fo(k, 1, i - 1) {
int cost = f[k][j - 1];
cost -= get_num(a[i], a[n]) * (a[i] - a[k]);
int l = a[k], r = a[i], mid = l + r >> 1;
cost -= gsum(mid + 1, a[i] - 1) - a[k] * get_num(mid + 1, a[i] - 1);
cost += a[i] * get_num(mid + 1, a[i] - 1) - gsum(mid + 1, a[i] - 1);
f[i][j] = min(f[i][j], cost);
}
}
}
fo(i, m, n) ans = min(ans, f[i][m]);
pf("%d\n", ans);
}
O(n ^3)