中位數應用:輸油管道問題--快速排序、改進、變種

shuaishuai3409發表於2016-05-18

問題描述:某石油公司計劃建造一條由東向西的主輸油管道。該管道要穿過一個有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)

O(n^2)


輸油管道問題變種

  1. 管道不一定水平,可以任意方向旋轉
    本質上相當於座標軸旋轉確定新的座標。新的油井縱座標為y=y0cos(a)+x0sin(a)。原理和水平放置相同。通過遍歷a度數(度數a取值範圍0-180),每遍歷一個度數就執行中位數查詢,確定距離和Di

    D_i
    ,然後在所有的D中找最小的。

  2. 油井有權重
    若考慮每個油井即使和管道距離相同,但每個油井代價不同。此時該如何建立管道保證總代價最小。問題會轉換為帶權中位數問題

  3. 擴充:郵局選址問題
    輸油管道問題是一維的郵局選址問題。(待補充)

相關文章