生活随笔
收集整理的這篇文章主要介紹了
hdu1007最近点对问题(分冶java)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題目鏈接
題意就是給若干點(diǎn),求最近點(diǎn)對(duì)問(wèn)題。
- 首先這題是我很久前看到的,我那時(shí)候用了o(n^2)因?yàn)閿?shù)據(jù)量太大,計(jì)算太多超時(shí)。當(dāng)時(shí)看了別人的分析就說(shuō)分冶當(dāng)時(shí)看代碼太長(zhǎng)也就沒(méi)靜下心看。前天翻了數(shù)據(jù)結(jié)構(gòu)看到分冶算法的最近點(diǎn)問(wèn)題恍然大悟,一下子就懂了。理解了其中的奧秘。
- 對(duì)于分冶的問(wèn)題,就是一個(gè)問(wèn)題可以拆成若干個(gè)子問(wèn)題,若干個(gè)子問(wèn)題之間沒(méi)有聯(lián)系,并且這個(gè)問(wèn)題的處理方法同樣適用于子問(wèn)題。
首先上圖
如果用最暴力的方法,那么我們就是要將每?jī)蓚€(gè)點(diǎn)計(jì)算一遍,比較大小。如果有n個(gè)點(diǎn),那么就要計(jì)算n^2次。我們下面進(jìn)行初步優(yōu)化:
取中間點(diǎn),先算出所有左側(cè)點(diǎn)的距離最小值,再算出右側(cè)距離最小值,這兩個(gè)中更小的那個(gè)為min。這個(gè)距離不一定是最短的那個(gè)點(diǎn),因?yàn)橛锌赡茏疃痰哪莻€(gè)點(diǎn)再中間跨越兩邊。
- 我們思考一下,這個(gè)中間兩點(diǎn)一個(gè)在左,一個(gè)在右,兩個(gè)點(diǎn)的橫坐標(biāo)之差一定小于 min不然他的投影都大于最短,所以我只需要處理中間左右區(qū)間為min里面的點(diǎn)進(jìn)行處理,對(duì)于這些點(diǎn),左右距離是小于min的,如果上下距離大于min,就跳過(guò)不在考慮。
- 考慮一下計(jì)算量,左側(cè)(n^2) /4 右側(cè) 也是,加起來(lái)是n*n/2,再加上中間的部分?jǐn)?shù)據(jù)。這是一次優(yōu)化的,另外,對(duì)于海量數(shù)據(jù),我們分析其左側(cè),我們也可以把左側(cè)拆成一半,先算左右再算中間,右側(cè)也是如此。并且問(wèn)題可以一直拆分直到不能在拆為止。這個(gè)復(fù)雜度的差距就出來(lái)了。
- 但是對(duì)于這個(gè)題,如果取x排序分冶事件耗費(fèi)也比較大,這個(gè)可能就是點(diǎn)都大部分聚集在中間,上下間距較大的緣故,我們采用y排序劃分分冶。效率還是很高的。
附上代碼
import java
.io
.BufferedReader
;
import java
.io
.IOException
;
import java
.io
.InputStreamReader
;
import java
.io
.OutputStreamWriter
;
import java
.io
.PrintWriter
;
import java
.io
.StreamTokenizer
;
import java
.util
.ArrayList
;
import java
.util
.Arrays
;
import java
.util
.Comparator
;
import java
.util
.List
;
public class Main {static int n
;public static void main(String
[] args
) throws IOException
{StreamTokenizer in
=new StreamTokenizer(new BufferedReader(new InputStreamReader(System
.in
)));PrintWriter out
= new PrintWriter(new OutputStreamWriter(System
.out
));while(in
.nextToken()!=StreamTokenizer
.TT_EOF
){n
=(int)in
.nval
;if(n
==0) {break;}node no
[]=new node[n
];for(int i
=0;i
<n
;i
++){in
.nextToken();double x
=in
.nval
;in
.nextToken();double y
=in
.nval
;no
[i
]=new node(x
,y
);}Arrays
.sort(no
, com
);double min
= search(no
,0,n
-1);out
.println(String
.format("%.2f", Math
.sqrt(min
)/2));out
.flush();} }private static double search(node
[] no
, int left
,int right
) {int mid
=(right
+left
)/2;double minleng
=0;if(left
==right
) {return Double
.MAX_VALUE
;}else if(left
+1==right
) {minleng
= (no
[left
].x
-no
[right
].x
)*(no
[left
].x
-no
[right
].x
)+(no
[left
].y
-no
[right
].y
)*(no
[left
].y
-no
[right
].y
);}else minleng
= min(search(no
,left
,mid
),search(no
,mid
,right
));int ll
=mid
;int rr
=mid
+1;while(no
[mid
].y
-no
[ll
].y
<=Math
.sqrt(minleng
)/2&&ll
-1>=left
) {ll
--;}while(no
[rr
].y
-no
[mid
].y
<=Math
.sqrt(minleng
)/2&&rr
+1<=right
) {rr
++;}for(int i
=ll
;i
<rr
;i
++){for(int j
=i
+1;j
<rr
+1;j
++){double team
=0;if(Math
.abs((no
[i
].x
-no
[j
].x
)*(no
[i
].x
-no
[j
].x
))>minleng
) {continue;}else{ team
=(no
[i
].x
-no
[j
].x
)*(no
[i
].x
-no
[j
].x
)+(no
[i
].y
-no
[j
].y
)*(no
[i
].y
-no
[j
].y
);if(team
<minleng
)minleng
=team
;}}}return minleng
;}private static double min(double a
, double b
) {return a
<b
?a
:b
;}static Comparator
<node>com
=new Comparator<node>() {@Overridepublic int compare(node a1
, node a2
) {return a1
.y
-a2
.y
>0?1:-1;}};static class node{double x
;double y
;public node(double x
,double y
){this.x
=x
;this.y
=y
;}}
}
如果對(duì)后端、爬蟲、數(shù)據(jù)結(jié)構(gòu)算法等感性趣歡迎關(guān)注我的個(gè)人公眾號(hào)交流:bigsai
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的hdu1007最近点对问题(分冶java)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。