生活随笔
收集整理的這篇文章主要介紹了
HDU1007 查找平面最近点对
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
求點(diǎn)集中的最近點(diǎn)對有以下兩種方法:
設(shè)p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n個點(diǎn)構(gòu)成的集合S,設(shè)計(jì)算法找出集合S中距離最近的點(diǎn)對。
?OJ題目:HDU1007http://acm.hdu.edu.cn/showproblem.php?pid=1007
1、蠻力法(適用于點(diǎn)的數(shù)目比較小的情況下)
1)算法描述:已知集合S中有n個點(diǎn),一共可以組成n(n-1)/2對點(diǎn)對,蠻力法就是對這n(n-1)/2對點(diǎn)對逐對進(jìn)行距離計(jì)算,通過循環(huán)求得點(diǎn)集中的最近點(diǎn)對:
2、分治法
1)算法描述:已知集合S中有n個點(diǎn),分治法的思想就是將S進(jìn)行拆分,分為2部分求最近點(diǎn)對。算法每次選擇一條垂線L,將S拆分左右兩部分為SL和SR,L一般取點(diǎn)集S中所有點(diǎn)的中間點(diǎn)的x坐標(biāo)來劃分,這樣可以保證SL和SR中的點(diǎn)數(shù)目各為n/2,
(否則以其他方式劃分S,有可能導(dǎo)致SL和SR中點(diǎn)數(shù)目一個為1,一個為n-1,不利于算法效率,要盡量保持樹的平衡性)
依次找出這兩部分中的最小點(diǎn)對距離:δL和δR,記SL和SR中最小點(diǎn)對距離δ = min(δL,δR),如圖1:
?
以L為中心,δ為半徑劃分一個長帶,最小點(diǎn)對還有可能存在于SL和SR的交界處,如下圖2左圖中的虛線帶,p點(diǎn)和q點(diǎn)分別位于SL和SR的虛線范圍內(nèi),在這個范圍內(nèi),p點(diǎn)和q點(diǎn)之間的距離才會小于δ,最小點(diǎn)對計(jì)算才有意義。
?
Figure 2
?
對于SL虛框范圍內(nèi)的p點(diǎn),在SR虛框中與p點(diǎn)距離小于δ的頂多只有六個點(diǎn),就是圖二右圖中的2個正方形的6的頂點(diǎn)。這個可以反推證明,如果右邊這2個正方形內(nèi)有7個點(diǎn)與p點(diǎn)距離小于δ,例如q點(diǎn),則q點(diǎn)與下面正方形的四個頂點(diǎn)距離小于δ,則和δ為SL和SR中的最小點(diǎn)對距離相矛盾。因此對于SL虛框中的p點(diǎn),不需求出p點(diǎn)和右邊虛線框內(nèi)所有點(diǎn)距離,只需計(jì)算SR中與p點(diǎn)y坐標(biāo)距離最近的6個點(diǎn),就可以求出最近點(diǎn)對,節(jié)省了比較次數(shù)。
(否則的話,最壞情形下,在SR虛框中有可能會有n/2個點(diǎn),對于SL虛框中的p點(diǎn),每次要比較n/2次,浪費(fèi)了算法的效率)
[cpp] view plaincopy
#include?<iostream>??#include?<cstring>??#include?<algorithm>??#include?<cstdio>??#include?<cmath>??using?namespace?std;??struct?point??{??????double?x,y;??}p[100005];??int?a[100005];??int?cmpx(const?point?&a,const?point?&b)??{??????return?a.x?<?b.x;??}??int?cmpy(const?int?&a,const?int?&b)??{??????return?p[a].y?<?p[b].y;??}??double?dis(int?a,int?b)??{??????return?sqrt((p[a].x?-?p[b].x)?*?(p[a].x?-?p[b].x)?+?(p[a].y?-?p[b].y)?*?(p[a].y?-?p[b].y));??}??double?min(double?x,double?y)??{??????return?x?<?y???x?:?y;??}??double?cloest(int?left,?int?right)??{??????if(left?==?right)??????????return?1000000;??????if(left?+?1?==?right)??????????return?dis(left,right);??????int?mid?=?(left?+?right)?>>?1;??????double?d1?=?cloest(left,mid);???????????double?d2?=?cloest(mid+1,right);?????????double?d?=?min(d1,d2);??????int?i,j,k?=?0;??????for(?i?=?left?;?i?<=?right;?i++?)??????{??????????if(fabs(p[mid].x?-?p[i].x)?<?d)???????????????????a[k++]?=?i;??????????????}??????sort(a,a+k,cmpy);??????????for(?i?=?0;?i?<?k?-?1;?i++?)???????????{??????????for(?j?=?i+1;?j?<?i?+?7?&&?j?<?k;?j++?)??????????{??????????????if(p[a[j]].y?-?p[a[i]].y?>=?d)??????????????????break;??????????????d?=?min(d,dis(a[i],a[j]));??????????}??????}??????return?d;????}??int?main()??{??????int?i,n;??????while(scanf("%d",&n)?!=?0)??????{??????????if(!n)??????????????break;??????????for(?i?=?0;?i?<?n;?i++?)??????????{??????????????scanf("%lf?%lf",&p[i].x,&p[i].y);??????????}??????????sort(p,p+n,cmpx);??????????????printf("%.2f\n",cloest(0,n-1)?/?2);??????}??????return?0;??}?
總結(jié)
以上是生活随笔為你收集整理的HDU1007 查找平面最近点对的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。