1206 POJ1485 Fast Food

2 篇文章 0 订阅
摘要
同一条路上的餐馆,要修建仓库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 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


题目理解
-这个题目想了好久。最后通过搜索结合记忆化把它解决了;对于给定的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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值