摘要
题目理解
同一条路上的餐馆,要修建仓库depots;给定仓库的数量和这条路上所有餐馆的位置;求合理的分配方式(总的餐馆距最近的depot距离之和最小);
原题目摘要
-Fast Food
http://poj.org/problem?id=1485
-
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
n∑ |di - (position of depot serving restaurant i)|i=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 contains several descriptions of fastfood chains. Each description starts with a line containing the two integers n and k. n and k will satisfy 1 <= n <= 200, 1 <= k <= 30, k <= n. Following this will n lines containing one integer each, giving the positions di of the restaurants, ordered increasingly.
The input file will end with a case starting with n = k = 0. This case should not be processed.
Output
For each chain, first output the number of the chain. Then output an optimal placement of the depots as follows: for each depot output a line containing its position and the range of restaurants it serves. If there is more than one optimal solution, output any of them. After the depot descriptions output a line containing the total distance sum, as defined in the problem text.
Output a blank line after each test case.
Sample Input
6 3
5
6
12
19
20
27
0 0
Sample Output
Chain 1Depot 1 at restaurant 2 serves restaurants 1 to 3Depot 2 at restaurant 4 serves restaurants 4 to 5
Depot 3 at restaurant 6 serves restaurant 6Total distance sum = 8
题目理解
-这个题目想了好久。最后通过搜索结合记忆化把它解决了;对于给定的k个depots 与 n个餐馆;总可以找到至少一个点满足要求 这个点搜索的话 是 min(dp(1,begin,mid)+(k-1,mid+1,end)) mid的取值范围是begin到end-k+1;如果用三维数组 中间很多没用上;利用两个二维数组;Dij[][];用来储存任意的i到j之间有一个depot时的距离和;Dki[][]用来记录分割数据,从i到结束中间用k个depots时的距离总和,每个分割点记录分割起点b,分割偏移pos,当前i到end分配距离总和,下一个分割点*next;
注意
-输出的是时候摔了跟头;单个和多个的restaurant(s);最后一个分割的输出;与前面的不同;每个测试数据间有一空行。
日期
-2017 12 6
附加
-
代码
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <memory>
#define MAX 205
using namespace std;
struct Node{
int b;
int pos;//next div pos
int cur_total;//B TO END AL LCOST
Node *next;
void init(int _b){
b=_b;next=NULL;cur_total = pos= -1;
}
};
int D[MAX];
int n,k;
int id;
int Dij[MAX][MAX];//use getij();
Node Dki[31][MAX];//use for the dp();
int getDij(int b,int e){
if(Dij[b][e]!=-1) return Dij[b][e];
int cur=0;
int p = (b+e)/2;
for(int i=b;i<=e;i++){
cur+=abs(D[p]-D[i]);
}
return Dij[b][e]=cur;
}
Node dp(int _k,int _b){
//cout<<_k<<" "<<_b<<" "<<Dki[_k][_b].cur_total<<endl;
if(Dki[_k][_b].pos!=-1) return Dki[_k][_b];
Node &node = Dki[_k][_b];
node.b = _b;
if(_k==1){
node.pos = (n-1+_b)/2-_b;
node.cur_total = getDij(_b,n-1);
node.next = NULL;
return Dki[_k][_b];
}
node.cur_total = dp(_k-1,_b+1).cur_total;
node.next = &Dki[_k-1][_b+1];
node.pos = 0;
int temp;
for(int i=1;_b+i<=n-_k;i++){
temp = getDij(_b,_b+i)+dp(_k-1,_b+i+1).cur_total;
if(temp<node.cur_total){
node.cur_total = temp;
node.next = &Dki[_k-1][_b+i+1];
node.pos = i;
}
}
return Dki[_k][_b];
}
void show_node(Node *it,int o){
int b=it->b+1;
int e=b+it->pos;
int p=b+it->pos/2;
if(o==k){//last depot
p=e;
e=n;
}
printf("Depot %d at restaurant %d serves restaurant",
o,p);
if(b!=e)printf("s %d to %d\n",b,e);
else printf(" %d\n",b);
}
void solve(){
for(int i=0;i<n;i++)scanf("%d",&D[i]);
for(int i=1;i<=k;i++){
for(int j=0;j<n;j++)
Dki[i][j].init(j);
}
memset(Dij,-1,sizeof(Dij));
dp(k,0);
Node *ans = &Dki[k][0];
printf("Chain %d\n",id);
int o=1;
int total=ans->cur_total;
while(ans){
show_node(ans,o);o++;
ans = ans->next;
}
printf("Total distance sum = %d\n\n",total);
}
int main(){
freopen("in","r",stdin);
id = 0;
while( scanf("%d%d",&n,&k)&&n){
id++;solve();
}
return 0;
}