中位數應用:輸油管道問題--快速排序、改進、變種
問題描述:某石油公司計劃建造一條由東向西的主輸油管道。該管道要穿過一個有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
快速排序的改進:隨機選擇演算法。
在選擇基數位的時候,不是每次都選擇第一個數,而是以隨機的方式產生表示任意位置的隨機數來作為基數。從概率角度,這種做法不會達到最壞的時間複雜度
輸油管道問題變種:
管道不一定水平,可以任意方向旋轉
本質上相當於座標軸旋轉確定新的座標。新的油井縱座標為y=y0cos(a)+x0sin(a)。原理和水平放置相同。通過遍歷a度數(度數a取值範圍0-180),每遍歷一個度數就執行中位數查詢,確定距離和Di D_i,然後在所有的D中找最小的。油井有權重
若考慮每個油井即使和管道距離相同,但每個油井代價不同。此時該如何建立管道保證總代價最小。問題會轉換為帶權中位數問題。擴充:郵局選址問題
輸油管道問題是一維的郵局選址問題。(待補充)
相關文章
- 用“歸併”改進“快速排序” (轉)排序
- 加權中位數應用:油井加權的輸油管道位置選取
- C++輸入十進位制數,輸出對應二進位制數、十六進位制數C++
- Vijos / 題庫 / 輸油管道問題
- 敏捷改進應該問題驅動敏捷
- vue 變數賦值同時改變的問題Vue變數賦值
- 如何把十進位制的數輸入用二進位制全加器,並以十進位制輸出
- 負數的二進位制數問題
- 三種改變 PriorityQueue 排序方式的辦法排序
- 用c#進行快速排序C#排序
- Chrome渲染管道的效能改進Chrome
- Java中關於十進位制數取反問題解決Java
- 第一章:位運算-------輸入浮點數,輸出對應二進位制數
- printf()將10進位制數安照輸出16進位制,8進位制輸出
- js中變數作用域問題JS變數
- 三種快速排序排序
- 在c語言中輸出8進位制數,16進位制數C語言
- printf與scanf如何輸出、輸入十六進位制與八進位制數
- 求資料流中的中位數問題
- stoi字串轉十進位制數越界問題字串
- PB關於資料視窗內欄位值改變問題
- c/c++各種進位制輸出C++
- C#按字串中的數字排序問題C#字串排序
- 解鎖環境變數在雲原生應用中各種姿勢變數
- C語言資料型別、變數的輸入和輸出、進位制轉換C語言資料型別變數
- 三種快速排序法排序
- PHP中將ip地址轉成十進位制數的兩種實用方法PHP
- 對十進位制數字的按位輸出,取反,並求其位數
- 請問如何在java程式中動態改變輸入法設定。Java
- 快速掌握Java幾種排序演算法的區別與排序演算法的應用Java排序演算法
- 分治思想--快速排序解決TopK問題排序TopK
- postman中各種變數Postman變數
- php輸出帶變數字串(echo函式的應用)PHP變數字串函式
- 變數可變性問題變數
- 改變無法改變的Query 變數變數
- C++變數總結束 | 輸出各種變數的值C++變數
- 關於Java中進位制轉換以及位運算問題Java
- shell指令碼中的變數及應用指令碼變數