P1429-平面最近点对(加强版)【分治】
生活随笔
收集整理的這篇文章主要介紹了
P1429-平面最近点对(加强版)【分治】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P1429
題目大意
平面上nnn個點,求最近點對
解題思路
考慮分治求最近點對,首先將平行于yyy軸將平面穿過xxx左邊的中位數分割成兩半,現在最近點對有三種可能,
我們知道1和2可以用分治到兩邊計算,考慮如何求情況3。暴力枚舉對數肯定會TLETLETLE,考慮優化,假設我們已經知道1和2的最小解d1,d2d1,d2d1,d2了,我們有d=min{d1,d2}d=min\{d1,d2\}d=min{d1,d2},那么我們可以以分割線為對稱軸做一個2d?d2d*d2d?d的矩形,最近點對的兩個點一定在這個矩形內。
這樣計算為什么可以優化算法?因為矩陣內的點數是常數級別的,首先我們可以由分割線分割成兩個小正方形,我們知道正方形內的點距離一定不小于ddd,那么一個正方形內最多只有常數級別的點數(好像是3個的樣子)
所以時間復雜度O(nlog?n)O(n\log n)O(nlogn)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=2e5+10; int n,p[N],c[N]; double x[N],y[N]; bool cmp(int a,int b) {return (x[a]==x[b])?(y[a]<y[b]):(x[a]<x[b]);} bool cMp(int a,int b) {return y[a]<y[b];} double get_dis(int a,int b) {return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));} double Solve(int l,int r){double d=1e18;if(l==r)return d;if(l+1==r)return get_dis(p[l],p[r]);int mid=(l+r)>>1;double d1=Solve(l,mid);double d2=Solve(mid+1,r);d=min(d1,d2);int tot=0;for(int i=l;i<=r;i++)if(fabs(x[p[i]]-x[p[mid]])<=d)c[++tot]=p[i];sort(c+1,c+1+tot,cMp);for(int i=0;i<tot;i++){for(int j=i+1;j<=tot;j++){if(y[c[j]]-y[c[i]]>=d)break;double D=get_dis(c[i],c[j]);d=min(d,D);}}return d; } int main() {scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%lf%lf",&x[i],&y[i]);p[i]=i;}sort(p+1,p+1+n,cmp);printf("%.4lf",Solve(1,n)); }總結
以上是生活随笔為你收集整理的P1429-平面最近点对(加强版)【分治】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P2480-[SDOI2010]古代猪文
- 下一篇: P4027-[NOI2007]货币兑换【