Raid 平面最近點對

2022-05-19 06:19:31 字數 2585 閱讀 3378

《更新提示》

《第一次更新》

《正文》

平面最近點對算是乙個經典的問題了,雖然談不上是什麼專門的演算法,但是拿出問題模型好好分析乙個是有必要的。

給定\(n\)個二元組\((x,y)\),代表同一平面內的\(n\)個點的座標,求\(\min\\}\)。

其中,定義\(dis_\)代表兩點的直線距離,即\(dis_=\sqrt\)。

\(solution\ 1:\)

暴力求解,\(o(n^2)\)列舉兩點,直接計算更新答案。

\(solution\ 2:\)

分治,先將所有點以橫座標為第一關鍵字,縱座標為第二關鍵字排序。

定義乙個問題\(divide(l,r)\)代表排序後點\(l\)到點\(r\)這一段的最優解。然後,對於每乙個問題,我們取乙個中間點\(mid=(l+r)/2\),那麼這個問題的解可以分三種情況討論:

\(1.\)最優的點對在點\(mid\)左側(包括\(mid\))

\(2.\)最優的點對在點\(mid\)右側

\(3.\)最優的點對乙個在\(mid\)左側(包括\(mid\)),乙個在\(mid\)右側

顯然,對於\(1.2.\)兩種情況,我們可以直接通過遞迴呼叫子問題\(divide(l,mid)\)和\(divide(mid+1,r)\)來求解,那麼我們最大的問題就是解決第三種情況。

試想,如果我們暴力列舉兩邊的點,那麼時間複雜度仍為\(o(n^2)\),分治就失去了意義。考慮乙個優化,假設我們已經得到子問題的答案\(d=\min\\),那麼任何乙個橫座標距\(mid\)大於\(d\)的點都不可能成為更優的解

那麼我們開乙個臨時陣列,將所有橫座標距\(mid\)小於等於\(d\)的點加入這個陣列中,然後到這個數字中列舉找到最優解。

考慮再優化一下,設上一步操作得到的點集為\(s\),那麼我們還可以將\(s\)按縱座標排序,如果更新最優解時發現兩點縱座標之差大於\(d\),可以直接退出迴圈,達到優化的效果。

事實上,可以證明,只列舉橫縱座標與\(mid\)之差小於\(d\)的點,這樣的點至多只有\(6\)個,對時間複雜度的貢獻是常數級別的,那麼分治的時間複雜度就是遞迴的時間複雜度加上每次掃瞄加入備選答案點集的時間複雜度,很容易計算得出時間複雜度為\(o(nlog_2n)\)。

關於上文提到點集大小小於等於\(6\)的詳細證明,可以看這個部落格。

在與聯盟的戰鬥中連續失敗後,帝國撤退到最後乙個據點。 根據其強大的防禦系統,帝國擊退了聯盟攻擊的六波浪潮。 經過幾個不眠之夜,聯盟將軍亞瑟注意到,防禦系統唯一的弱點就是能源**。 該系統由n個核電站充電,其中任何乙個都會使系統失效。

這位將軍很快就開始對n個**人員進行突襲,這些**人員進入了據點。 不幸的是,由於帝國空軍的襲擊,他們未能降落在預期位置。 作為一名經驗豐富的將軍,亞瑟很快意識到他需要重新安排計畫。 他現在想知道的第一件事就是哪個**商離任何乙個發電站最近。 你是否可以幫助將軍計算**人和車站之間的最小距離?

第一行是表示測試用例數的整數t. 每個測試用例以整數n開頭。 (1 ≤≤ n ≤≤ 100000). 接下來的n行描述了站點的位置。 每行包括兩個整數x(0 ≤≤ x ≤≤ 1000000000)和y(0 ≤≤ y ≤≤ 1000000000),表示該站的位置。 接下來的n行描述了**的位置。 每行包含兩個整數x(0 ≤≤ x ≤≤ 1000000000)和y(0 ≤≤ y ≤≤ 1000000000),表示**的位置。

對於每個測試用例輸出,最小距離精度為三位小數放在乙個單獨的行中。

2

40 0

0 11 0

1 12 2

2 33 2

3 34

0 00 0

0 00 0

0 00 0

0 00 0

1.414

0.000

這道就是平面最近點對模板題嘛。給定\(2n\)個點,求第乙個點集中的點到第二個點集中的點的最短距離。對於不同的點集的點,我們直接定義距離為正無窮,然後分治就可以了。

\(code:\)

#includeusing namespace std;

#define mset(name,val) memset(name,val,sizeof name)

#define filein(str) freopen(str".in","r",stdin)

#define fileout(str) freopen(str".out","w",stdout)

const int n=100000+20;

const double inf=1e30,eps=1e-5;

int n;

struct nodevertex[2*n];

inline void input(void)

}inline double dis(node a,node b)

inline bool comparex(node a,node b) }

return res;

}int main(void)

return 0;

}

《後記》

poj 3714 Raid(平面最近點對)

給出兩個點集,然後求兩個點集之間的最近距離。思路 開始用的旋轉卡殼,兩個點集先求凸包,這樣就變成了兩個凸包間最近距離,但是死活tle,然後就換了平面最近點對來做,把兩個點集標記一下,判斷下是不是在同乙個點集裡就行了 include include include using namespace st...

POJ 3714 Raid 平面最近點對

題目大意 給出兩個集合的點,問這兩個集合之間最近的點對的距離是多少。思路 先要知道平面最近點對的分治演算法,剩下的就簡單了,只需要在更新答案的時候判斷一下兩個點是否屬於兩個集合就可以了。分治演算法總是十分神奇的。對於平面最近點對,首先按照x座標排序,然後遞迴進行分治,每次分治時,先獲得分治得到的結果...

poj 3714 Raid(平面最近點對)

題意 給定在同一平面中,同數量黑點與白點的座標值,求其中最近黑白點對的距離。大水題一遍過qaq 稍微做點工作就是把同顏色的點,做上標記,同顏色的點就使其之間距離inf 分治or暴力 剪枝都可以過。include include include include include using namesp...