中位数应用:输油管道问题--快速排序、改进、变种

问题描述:某石油公司计划建造一条由东向西的主输油管道。该管道要穿过一个有n口油井的油田。从每口油井都要有一条输油管道沿最短路经(或南或北)与主管道相连。示意如下所示。如果给定n口油井的位置, 即它们的x坐标(东西向)和y坐标(南北向), 应如何确定主管道的最优位置, 即使各油井到主管道之间的输油管道长度总和最小的位置?
这里写图片描述


问题分析:问题可以抽象为给定n个点坐标,如何确定一条平行于x轴的直线,使得所有的点到直线的距离和最短。进一步简化为只提取n个点的纵坐标,保存进数组中,目标是确定直线的纵坐标使得距离和最短。


解决方案:给定点的个数可能为奇数或偶数,两种情况对直线的位置确定影响不同。

对于偶数点情况:当直线在a2-a3之间的时候,距离和D=(a3-a2)+(a4-a1),当直线在别的位置比如a1-a2时,距离和D=(a3-a2)+(a4-a1)+d,其中d为偏移量。我们会发现只有直线位置属于[a2,a3]时,距离和才会最小,而且在[a2,a3]任意位置,距离和都是固定的。所以没有必要将直线取值在a2和a3的正中间,取a2和a3能有相同的效果,相当于a2和a3中间位置取整,这就说明找到n个点的中位数即可。
这里写图片描述

对于奇数点情况:和偶数点相同,也是找中位数。直线位于a2时,距离和D=a3-a1,当直线偏离a2,位于a1-a2间时,距离和D=a3-a1+d,d为a2偏移量。也能说明只有直线位于中位数位置时,距离和最短,是我们要找的位置。
这里写图片描述


详细细节:对于输入的数据,提取纵坐标保存到数组中,然后排序,找到中位数。众多排序算法中,快排平均性能最优,故先选择快排,然后提取中位数。

实现代码:

#include<iostream>
#include<vector>
#define len 10 
using namespace std;
void quickSort(int[] , int, int);
int main(){
    vector<int> list;
    //读入n个油井纵坐标的位置
    list.push_back(5);
    list.push_back(9);
    list.push_back(2);
    list.push_back(9);
    //cout << "容器大小为: " << list.size() << endl;
    int array[len] = {};
    //将向量转换为数组,主要考虑到传参时,数组是指针。
    for (int i = 0; i < list.size(); i++)
        array[i] = list.at(i);
    quickSort(array, 0, list.size()-1);
    //cout<<list.at(1)<<endl;
    //list.at(1) = 4;
    for (int i = 0; i < list.size(); i++)
        cout << array[i] << endl;
    cout<<"输油管道放置位置坐标:y=" << array[list.size() / 2-1]<<endl;

}
void quickSort(int a[], int left, int right)
{
    if (left<right)
    {
        int i = left;
        int j = right;
        int x = a[i];

        while (i<j)
        {
            while (i<j&&a[j]>x)
                j--;
            if (i<j){
                a[i] = a[j];
                i++;
            }
            while (i<j&&a[i]<x)
                i++;
            if (i<j){
                a[j] = a[i];
                j--;
            }
        }
        a[i] = x;
        quickSort(a, left, i - 1);
        quickSort(a, i + 1, right);
    }
}
结果:
油井纵坐标:2
油井纵坐标:5
油井纵坐标:9
油井纵坐标:9
输油管道放置位置坐标:y=5

快速排序的改进:随机选择算法。

在选择基数位的时候,不是每次都选择第一个数,而是以随机的方式产生表示任意位置的随机数来作为基数。从概率角度,这种做法不会达到最坏的时间复杂度 O(n2)


输油管道问题变种

  1. 管道不一定水平,可以任意方向旋转
    本质上相当于坐标轴旋转确定新的坐标。新的油井纵坐标为y=y0cos(a)+x0sin(a)。原理和水平放置相同。通过遍历a度数(度数a取值范围0-180),每遍历一个度数就执行中位数查找,确定距离和 Di ,然后在所有的D中找最小的。

  2. 油井有权重
    若考虑每个油井即使和管道距离相同,但每个油井代价不同。此时该如何建立管道保证总代价最小。问题会转换为带权中位数问题

  3. 拓展:邮局选址问题
    输油管道问题是一维的邮局选址问题。(待补充)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值