http://acm.fzu.edu.cn/problem.php?pid=1005
Description
The fastfood chain McBurger owns several restaurants along a highway. Recently, they have decided to build several depots along the highway, each one located at a restaurant and supplying several of the restaurants with the needed ingredients. Naturally, these depots should be placed so that the average distance between a restaurant and its assigned depot is minimized. You are to write a program that computes the optimal positions and assignments of the depots.
To make this more precise, the management of McBurger has issued the following specification: You will be given the positions of n restaurants along the highway as n integers d1 < d2 < ... < dn (these are the distances measured from the company's headquarter, which happens to be at the same highway). Furthermore, a number k (k <= n) will be given, the number of depots to be built.
The k depots will be built at the locations of k different restaurants. Each restaurant will be assigned to the closest depot, from which it will then receive its supplies. To minimize shipping costs, the total distance sum, defined as
![(记忆化搜索)Jury Compromise (poj 1015) (记忆化搜索)Jury Compromise (poj 1015)](https://image.shishitao.com:8440/aHR0cHM6Ly9iYnNtYXguaWthZmFuLmNvbS9zdGF0aWMvTDNCeWIzaDVMMmgwZEhBdk4zaHFiMkkwTG1OdmJURXVlakF1WjJ4aUxtTnNiM1ZrWkc0dVkyOXRMMkk1WWpCbU56a3pNV00zWkRZeFptUTNaV0ZoTXpJNE0ySXdPVFU1WWpGbC5qcGc%3D.jpg?w=700&webp=1)
must be as small as possible.
Write a program that computes the positions of the k depots, such that the total distance sum is minimized.
Input
The input file will end with a case starting with n = k = 0. This case should not be processed.
Output
Output a blank line after each test case.
Sample Input
Sample Output
n个旅馆和k个补给站的问题
假设有3个旅馆坐标分别是 1, 4, 5, 和2个补给站,那么路程代价就是1了,一个补给站放在坐标为1的旅馆那,令一个放在4位置处。
也可以一个补给站放在坐标为 1 的旅馆那,令一个放在 5 位置处。
//dp[i][k]表示前i个店添加k个供应点所达到的最小值
//状态转移方程为:dp[i][k] = min(dp[j][k-1], sum[j+1][i]),
//其中k-1 <= j <= i-1, sum[i][j]表示从第i个饭店到第j个饭店添加一个供应点所达到的最小值,取i,j中间值即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
#include <map>
using namespace std; #define N 220
#define MOD 1000000007
#define met(a, b) memset(a, b, sizeof(a))
#define INF 0x3f3f3f3f int dp[N][N], sum[N][N], a[N]; int main()
{
int n, m, iCase=; while(scanf("%d%d", &n, &m), n||m)
{
int i, j, k; for(i=; i<=n; i++)
scanf("%d", &a[i]); for(i=; i<=n; i++)
{
sum[i][i] = ;
for(j=i+; j<=n; j++)
{
sum[i][j] = sum[i][j-] + a[j] - a[(i+j)/];
}
} for(i=; i<=n; i++)
for(j=; j<=m; j++)
dp[i][j] = INF; dp[][] = ;
for(i=; i<=n; i++)
{
for(k=; k<=m; k++)
{
for(j=k-; j<i; j++)
{
dp[i][k] = min(dp[i][k], dp[j][k-]+sum[j+][i]);
}
}
} printf("Chain %d\n", iCase++);
printf("Total distance sum = %d\n\n", dp[n][m]);
}
return ;
}
记忆化搜索:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
#include <map>
using namespace std; #define N 220
#define met(a, b) memset(a, b, sizeof(a))
#define INF 0xffffff
const long long Max = ;
typedef long long LL; int a[N], sum[N][N], dp[N][N];
int n, m; int DFS(int x, int y)
{
int j; if(x< || y<) return INF; if(dp[x][y]!=INF) return dp[x][y]; if(y>=x) ///这点我还是想不到
{
dp[x][y] = ;
return ;
} for(j=; j<=x; j++) ///在 [1,x] 中选择一个点作为补给站
dp[x][y] = min(dp[x][y], DFS(j-, y-) + sum[j][x]); return dp[x][y];
} int main()
{
int iCase=; while(scanf("%d%d", &n, &m), n||m)
{
int i, j; met(sum, );
met(a, ); for(i=; i<=n; i++)
scanf("%d", &a[i]); for(i=; i<=n; i++)
for(j=i+; j<=n; j++)
sum[i][j] = sum[i][j-] + a[j]-a[(i+j)/]; for(i=; i<=n; i++)
for(j=; j<=m; j++)
dp[i][j] = INF; dp[n][m] = DFS(n, m); printf("Chain %d\n", iCase++);
printf("Total distance sum = %d\n\n", dp[n][m]);
}
return ;
}