POJ1160 Post Office
题目描述
在笔直的大道上建有$n$个大别墅,两个大别墅之间的距离是他们的横坐标之差的绝对值,保证大别墅之间的距离只能是整数,且没有别墅的位置是相同的。
现在需要建立$m$座大超市$(m \leq n)$,大超市只能建立在别墅所在的位置,现在需要你写个程序,给定了所有别墅的位置和大超市的数目,计算出每个别墅离最近的大超市的距离总和的最小值。
输入格式
第一行包括两个整数$n$和$m$
第二行包括n个整数,代表别墅的位置,以升序的形式列出。对于每一个整数$x$.
样例输入
10 5
1 2 4 6 7 10 11 25 44 70
样例输出
11
数据范围
$1 <= n <= 300$
$1 <= m <= 30$
$m <= n$
$1 <= X <= 10000$
我们先考虑这样一个问题:三个别墅分别在$(1, 7, 20)$中选一个超市,最小的距离和是多少。
答案是在中间那个超市,因为$(20-1+1) ÷ 2 = 10$,离$10$最近的超市是7,所以我们选中间这个别墅做超市,那么再来有5个别墅的情况:
答案还是离$(20-1+1) ÷ 2=10$的最近的别墅7,所以我们得出一个结论: 只有超市位于中间位置,距离和才最小
注意这个位置不是中间的那个别墅,而是离中间的那个地方最近的别墅。
设$dp[i][j]$表示考虑前$i$个别墅建$j$个超市的最小代价。
那么$dp[i][j]$可以从哪个地方转移过来呢?
$dp[k][j - 1]$,因为我们可以把$k$前面的别墅分成一块$k$到$i$的别墅另外分成一块,这一块只建一个超市。
所以状态转移方程是:$$dp[i][j]=min(dp[i][j],\text{ }\text{ }dp[k][j-1]+dis[k+1][i])$$
注:$dis[i][j]$表示第i个别墅到第j个别墅只建一个超市的最小代价
这个$dis[i][j]$是需要预处理的,因为如果不预处理,每次就需要枚举最优决策点,时间复杂度为$O(P^2 V^2)$是会超时的,但是我们可以用$V^2$预处理$dis[i][j]$,那么时间复杂度就降成$O(P^2V)$就不会超时了。
那现在来看看这个$dis[i][j]$怎么算:
我们先去掉$i$~$j$区间的最后一个,即只剩下了$i$ ~ $j-1$,这个区间只建一个超市的最小代价是$dis[i][j-1]$,最后加上新加的这个节点的与最优决策点的差就行了。
#include <bits/stdc++.h>
using namespace std;
#define MAXN 305
#define INF 0x3f3f3f3f
int V, P;
int x[MAXN], dp[MAXN][MAXN], dis[MAXN][MAXN];
int main()
{
scanf("%d %d", &V, &P);
memset(dp, INF, sizeof(dp));
for(int i = 1; i <= V; i++)
scanf("%d", &x[i]);
for(int i = 1; i <= V; i++)
dis[i][i] = 0;
for(int i = 1; i <= V; i++)
for(int j = i + 1; j <= V; j++)
dis[i][j] = dis[i][j - 1] + x[j] - x[(i + j) / 2];
for(int i = 1; i <= V; i++)
dp[i][1] = dis[1][i];
for(int j = 1; j <= P; j++)
for(int i = j + 1; i <= V; i++)
for(int k = 1; k <= i; k++)
dp[i][j] = min(dp[i][j], dp[k][j - 1] + dis[k + 1][i]);
cout << dp[V][P] << endl;
return 0;
}
最优决策点不应该是中位数么
这里应该是用到了货仓选址 $\sum_0^{i-1}\left|a_i-a_{n/2}\right|=\sum_0^{i-1}{a_i-a_{i/2}}$ 这个结论
有道理
你的意思是楼主的最优决策点不是中位数?
这个最优决策点怎么得来的?(蒟蒻求问)
货仓选址 题库搜索即可