工厂分布距离最短

1.12个工厂分布在一条东西向高速公路的两侧,工厂距离公路最西端的距离分别是0、4、5、10、12、18、27、30、 31、38、39、47.在这12个工厂中选取3个原料供应厂,使得剩余工厂到最近的原料供应厂距离之和最短, 问应该选哪三个厂 ?【问题来源于v_JULY_v的博客:http://blog.csdn.net/v_july_v/article/details/6880698

第一部分:思路

1. 工厂是按照距离从小到大排序好的

2. 在N个工厂中选出1个原材料供应厂,则选取中位数所在的工厂,距离是最短的

3. 设A(i,j)表示前i个工厂选取j个原料供应厂的最短距离,B(m,n)表示从第m个工厂到第n个工厂选取1个原材料供应厂的最短距离。则有如下推导式:

A(i,j) = Min { A(t,j-1) + B(t+1,i) }  1<=t<i, t>=j-1

第二部分:Java代码,不考虑异常情况

[java]  view plain copy
  1. /** 
  2.      * 12个工厂分布在一条东西向高速公路的两侧,工厂距离公路最西端的距离分别是0、4、5、10、12、18、27、30、 
  3.      * 31、38、39、47.在这12个工厂中选取3个原料供应厂,使得剩余工厂到最近的原料供应厂距离之和最短, 
  4.      * 问应该选哪三个厂 ? 
  5.      * @param factory 
  6.      * 每个工厂离公路最西端的距离 
  7.      * @param len 
  8.      * 工厂的数量 
  9.      * @param number 
  10.      * 原材料工供应厂的数量 
  11.      * @return 
  12.      * 返回1个number+1的数组,数组第1项为最短距离,余下number项为原材料供应厂 
  13.      */  
  14.     public static int[] select(int[] factory, int len, int number)  
  15.     {  
  16.         int[][] former = new int[len][number+1],  
  17.         latter = new int[len][number+1], tmp = null;  
  18.         //初始化  
  19.         for(int p=0;p<len;p++)  
  20.         {  
  21.             former[p][0] = distance(factory, 0, p);  
  22.             former[p][1] = factory[p>>1];           
  23.         }  
  24.         //动态规划  
  25.         for(int j=2;j<=number;j++)  
  26.         {  
  27.             for(int i=0;i<len;i++)  
  28.             {  
  29.                 if(i+1<j) //工厂的数量少于原材料供应厂  
  30.                 {  
  31.                     continue;  
  32.                 }else  
  33.                 {  
  34.                     latter[i][0] = Integer.MAX_VALUE;  
  35.                     for(int t=i-1;t>=0;t--)  
  36.                     {  
  37.                         if(t+1<j-1//工厂的数量少于原材料供应厂  
  38.                         {  
  39.                             continue;  
  40.                         }else  
  41.                         {  
  42.                             int curDis = former[t][0] + distance(factory, t+1, i);  
  43.                             if(latter[i][0]>curDis)  
  44.                             {  
  45.                                 latter[i][0] = curDis;  
  46.                                 for(int m=1;m<=j-1;m++)  
  47.                                 {  
  48.                                     latter[i][m] = former[t][m];  
  49.                                 }  
  50.                                 latter[i][j] = factory[(t+1+i)>>1];  
  51.                             }  
  52.                         }  
  53.                     }  
  54.                 }  
  55.             }  
  56.             //交换  
  57.             tmp = latter;  
  58.             latter = former;  
  59.             former = tmp;  
  60.         }  
  61.         return former[len-1];  
  62.     }  
  63.       
  64.     /** 
  65.      * 求从第m个工厂到第n个工厂设1个原料供应厂的最短距离 
  66.      */  
  67.     static int distance(int[] factory, int left, int right)  
  68.     {  
  69.         int mid = (left+right)>>1;  
  70.         int dis = 0;  
  71.         for(int i=left;i<=right;i++)  
  72.         {  
  73.             int dif = factory[i]-factory[mid];  
  74.             dis += ((dif>0)?dif:-1*dif);  
  75.         }  
  76.         return dis;  
  77.     }  

第三部分:测试用例

工厂:{0,4,5,10},选取1个原材料供应厂: {11,4},最短距离为11,选取4做原材料供应厂

工厂:{0,4,5,10},选取2个原材料供应厂: {5,4,10},最短距离为5,选取4,10做原材料供应厂

工厂:{0,4,5,10,12},选取2个原材料供应厂: {7,4,10},最短距离为7,选取4,10做原材料供应厂

工厂:{0,4,5,10,12},选取3个原材料供应厂: {3,0,4,10},最短距离为3,选取0,4,10做原材料供应厂

工厂:{0,4,5,10,12,18,27,30,31,38,39,47},选取3个原材料供应厂: {43,5,27,39},最短距离为43,选取5,27,39做原材料供应厂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值