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 restaurent 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 (these are the distances measured from the company's headquarter, which happens to be at the same highway). Furthermore, a number 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
Write a program that computes the positions of the k depots, such that the total distance sum is minimized.
The input file will end with a case starting with n = k = 0. This case should not be processed.
Input
Output
Output a blank line after each test case.
Sample Input
6 3 5 6 12 19 20 27 0 0
Sample Output
Chain 1
Depot 1 at restaurant 2 serves restaurants 1 to 3 Depot 2 at restaurant 4 serves restaurants 4 to 5 Depot 3 at restaurant 6 serves restaurant 6 Total distance sum = 8
题意:
给出n个点,要建k个depots,使得每个fastfood离最近的depots的总和最小。
思路:
先预处理sum数组,sum[i][j]-第i个位置到第j个位置建一个depots产生的距离和(建在中点位置距离和最小),预处理也是动态规划递推,画图很好找方程。
然后dp[i][j]表示处理到第i个位置建了j个depots的距离和。
那么有方程:
dp[i][j]=dp[k][j-1]+sum[k+1][i]; (k<i)
用数组存下最佳路径,于是问题解决了。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 1005 #define MAXN 100005 #define mod 1000000000 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 typedef long long ll; using namespace std; int n,m,ans,cnt,tot,flag; int a[maxn],res[maxn]; int dp[205][35],sum[205][205],pre[205][35]; void solve() { int i,j,t; memset(dp,0x3f,sizeof(dp)); for(i=1; i<=n; i++) dp[i][1]=sum[1][i]; for(i=1; i<=n; i++) { for(j=1; j<=m&&j<=i; j++) { for(int k=1; k<i; k++) { if(dp[i][j]>dp[k][j-1]+sum[k+1][i]) { dp[i][j]=dp[k][j-1]+sum[k+1][i]; pre[i][j]=k; } } } } } int main() { int i,j,t,test=0; while(scanf("%d%d",&n,&m),n|m) { for(i=1; i<=n; i++) { scanf("%d",&a[i]); } for(i=1; i<=n; i++) sum[i][i]=0; for(i=1; i<=n; i++) { for(j=i+1; j<=n; j++) { sum[i][j]=sum[i][j-1]+a[j]-a[(i+j)>>1]; } } solve(); printf("Chain %d\n",++test); t=n; for(i=m;i>=1;i--) { res[i]=t; t=pre[t][i]; } res[0]=0; for(i=1;i<=m;i++) { if(res[i-1]+1<res[i]) printf("Depot %d at restaurant %d serves restaurants %d to %d\n",i,(res[i]+res[i-1]+1)>>1,res[i-1]+1,res[i]); else printf("Depot %d at restaurant %d serves restaurant %d\n",i,res[i],res[i]); } printf("Total distance sum = %d\n\n",dp[n][m]); } return 0; }