• 算法导论 Exercises 9.39


    Problem Description:

    Professor Olay is consulting for an oil company, which is planning a large pipeline running east to west through an oil field of n wells.

    From each well, a spur pipeline is to be connected directly to the main pipeline along a shortest path (either north or south),

    as shown in Figure 9.2. Given x- and y-coordinates of the wells, how should the professor pick the optimal location of the main pipeline

    (the one that minimizes the total length of the spurs)? Show that the optimal location can be determined in linear time.

    问题描述:

    有n个已知坐标(x, y)的油井,现需要修一条沿x轴方向的主管道,每个油井通过y轴方向的分管道连接到主管道上。

    现需要给出主管道的位置(y坐标),使得所有油井连接到主管道所需的分管道总长度最小。

    问题抽象:

    可以看到,我们要确定的是主管道的y坐标,而分管道也是沿y轴方向的,故题中油井连接到主管道所需的分管道总长度与油井的x坐标无关。

    故以上问题可以抽象成一维的情况:

    在y轴上有n个点,其坐标(y1, y2, y3, ……, yn)已知,在y轴上找一点y0,使得这n个点到y0的距离和最小。

    为了排版方便,这里把y轴画成横向的。。。。。。

     

    解决方案:

    先看特殊的情况:

    n=2

    当只有两个点y1、y2时,y0只要在y1、y2之间的任意一点(包括端点)即可,此时分管道距离和等于|y1y2|。

    如果y0在y1左边或者y2右边,则距离和必然大于|y1y2|

    n=3

     

    此时,y0应当位于y2处,距离和等于|y1y2| + |y2y3|

     

    一般的,当n为偶数时:

    y0只要位于所有点中最中间的两个点之间(或端点上)即可取得最小的距离和。

    图中n=6时,y0只要位于[y3, y4]区间内即可取到最小距离和|y1y6|+|y2y5|+|y3y4|,而若将y0置于其它任意区间中时(比如ya或yb),

    其距离和必然大于|y1y6|+|y2y5|+|y3y4|

    当n为奇数时:

    同理可得,此时y0应位于奇数个点的中间点处。

    n=7时即为图中的y4处,距离和为:|y1y7|+|y2y6|+|y3y5|

     

    综上所述,若有n个点y1,y2,y3,……,yn,y0应取这n个点的中值数(⌊n+1⌋)。而找n个点的中值只要调用这篇文章里的算法 ithSmallestLinear 即可

    ithSmallestLinear这个算法已经被证明是O(n)的。

     

    实现代码:

    View Code
     1 //pick the optimal location of the main pipeline
     2 int pickOptiLoc(int coord[][2], int size, bool isXAxis)
     3 {
     4     int* subCoord = new int[size];
     5     int medianSeqNum = size / 2 + size % 2;
     6 
     7     for (int i = 0; i != size; ++i)
     8     {
     9         subCoord[i] = isXAxis ? coord[i][0] : coord[i][1];
    10     }
    11 
    12     return subCoord[ithSmallestLinear(subCoord, 0, size - 1, medianSeqNum)];
    13 }

    测试代码:

    View Code
     1 #define ARRAY_SIZE 15
     2 
     3 int wellLoc[ARRAY_SIZE][2];
     4 
     5 int main(void)
     6 {
     7     randArray(*wellLoc, ARRAY_SIZE * 2, 10, 99);
     8     for (int i = 0; i != ARRAY_SIZE; ++i)
     9     {
    10         std::cout << wellLoc[i][0] << " " << wellLoc[i][1] << std::endl;
    11     }
    12     std::cout << "optimal location of X axis : " 
    13               << pickOptiLoc(wellLoc, ARRAY_SIZE, true) << std::endl;
    14     std::cout << "optimal location of Y axis : " 
    15               << pickOptiLoc(wellLoc, ARRAY_SIZE, false) << std::endl;
    16 
    17     system("pause");
    18     return 0;
    19 }

     文中一些自定义函数的实现见文章“#include”

  • 相关阅读:
    CentOS7最小化安装后要做的事
    Django 2.0 新特性
    Django2.+ path配置
    Django 安装
    Django基础
    http协议
    Centos7 下mysql大小写敏感问题
    CentOS 设置mysql的远程访问
    Linux下彻底卸载mysql详解
    静态库和动态库
  • 原文地址:https://www.cnblogs.com/snser/p/2781730.html
Copyright © 2020-2023  润新知