演算法導論 分治法 最近點對 HDOJ1007

2021-06-21 02:14:12 字數 1631 閱讀 6433

hdoj1007的原題目是求出在不同時套中兩個玩具的前提下,圓圈的最大半徑。問題翻譯過來就是求解最近點對的問題,這個問題是經典的分治法問題。

參考部落格:

毫無疑問,通過暴力手段列舉所有的點對並計算這些點對的距離,找出最小的一組,可以得到最後的結果。但是,這道題的資料規模非常大,所以,這種傳統的方法肯定行不通。我試過,hdoj是超時的。

我對原部落格的第3步和第4步有不同的看法。

原部落格步驟:

1.讀取資料,並將點按橫座標公升序排列。

2.以最中間的那個點為基準,將平面內的點分為左右兩個部分。遞迴呼叫mindis(int,int)函式,分別求出左右兩個部分的點集的最短距離,並取兩者中的較小值,即為min.

3.顯然,min並不一定是最短距離,因為還可能存在一種情況,即點對中的乙個點位於左區域,另乙個點位於右區域。所以,我們取點集中橫座標與分界線的距離小於min的點,存入p2[n]陣列中。

4.對p2[n]陣列中的點按縱座標進行排序,計算p2[n]陣列中的點對的距離,如果存在小於min 的情況,就取代min作為最近距離。

最後,min即為平面內點集的最近距離。

我的步驟是:

1.讀取資料,並將點按橫座標公升序排列。

2.以最中間的那個點為基準,將平面內的點分為左右兩個部分。遞迴呼叫mindis(int,int)函式,分別求出左右兩個部分的點集的最短距離,並取兩者中的較小值,即為min.

3.顯然,min並不一定是最短距離,因為還可能存在一種情況,即點對中的乙個點位於左區域,另乙個點位於右區域。所以,我們取點集中橫座標與分界線的距離小於min的點,根據在分界線的左右,分別存入pxsmall[n]陣列和pxlarge[n]陣列中。

4.因為唯一可能的情況是乙個點在pxsmall[n],另乙個點在pxlarge[n]中。只要遍歷這個兩個陣列便可以了。

下面是在原部落格**上的修改:

#include#include#include#includeusing namespace std;

#define n 1000010

struct point

p1[n],pxsmall[n],pxlarge[n];

double dis ( point a , point b )

double min ( double a , double b )

} //直接遍歷兩個陣列

for(int i=0;i=mini)

break;

else if(dis (p2[j],p2[i])我在hdoj上分別跑這兩組**,發現原部落格runtime為1875ms,我的**runtime為1093ms,比原部落格的執行時間少了很多。因為少了排序這個步驟。當然,可能不同的資料集得到的執行時間不同,如果換乙個資料集或資料集規模很大的時候原部落格的方法可能更有優勢。但是有一點,我的方法更好地符合分治法的要求,正確性是可以保證的。最近一直在學習《演算法導論》,這本書真是神書,是演算法中的演算法,不僅僅告訴你演算法,還會告訴你演算法的證明。以後如果遇到分治法的問題,我會繼續補充到這篇部落格。

補充:參考部落格:

部落格中提到了飛機排程的問題,說的很好。可惜因為每個點的座標型別都是double型別的,不能直接找到那6個點,可以使用二分查詢,但是也不是特別方便。我隨便寫了**,時間上反而更長了。

演算法導論 筆記 分治法 最近點對問題

目錄 題目 在乙個 n 2 個點的集合 q 中尋找距離最近的點對 首先很容易想到暴力破解的方法,但是需要 o n2 的時間複雜度,所以考慮使用分治法,但將複雜度降為 o nlogn 還需要一些優化。關於執行時間的遞迴式為 t n 2t n2 o n 思路 把點集分為兩半,最近點對可能全部屬於左半點集...

分治法求最近點對

1 演算法描述 1.分割 將集合s進行以垂直於x軸的直線l進行平均劃分,並且保證sl和sr中的點數目各為n 2,否則以其他方式劃分s,有可能導致sl和sr中點數目乙個為1,乙個為n 1,不利於演算法效率,要盡量保持樹的平衡性 依次找出這兩部分中的最小點對距離 l和 r,記sl和sr中最小點對距離 m...

演算法分析分治法之最近點對問題

分治法 將乙個難以解決的問題,分成多個規模較小的問題逐個擊破,並將解決的子問題進行合併得到母問題的解決方案。最近點對問題 1.題目描述 給定二維平面上n個點,找其中的一對點,使得在n個點組成的所有點對中,該點對間的距離最小 2.輸入描述 n3.輸出描述 最近點對距離,結果保留2位小數 4.輸入樣例 ...