給定平面上n個點,找出其中的一對點的距離,使得在這n個點的所有點對中,該距離為所有點對中最小的
輸入格式:
第一行:n;2≤n≤200000
接下來n行:每行兩個實數:x y,表示乙個點的行座標和列座標,中間用乙個空格隔開。
輸出格式:
僅一行,乙個實數,表示最短距離,精確到小數點後面4位。
輸入樣例#1:
3 1 1
1 2
2 2
輸出樣例#1:
1.0000
0<=x,y<=10^9
這是一道分治。
首先,暴力列舉點對計算是n^2,肯定超。
然後資料範圍200000,就肯定是nlogn的演算法,然後我就想到二分答案,也進行了實現,然後,就沒有然後了。。。
於是我就愉快地看了題解,發現確實是二分,可是只是二分區間,然後再合併,就像歸併排序。
忽然發現很有道理,因為,點對是兩個點,然後就可以分治地去找到滿足條件的點對,並更新答案了。
然後,我就寫了一遍,還是很好寫的,真的很像歸併排序求逆序對。
然後我就交了一次:
結果60,我就當場懵逼。。
然後回去看題解,發現他寫了實數讀入優化,我就copy過來,想著試一試,又交了一次,然後:
wtf,這都行???
還有,為什麼還是有乙個wa?
於是我就開始看我和他的程式有什麼區別,發現排序的函式,他多判了一種x相等時比較y,我就加上了,然後重新交了一次:
還有這種操作???
這麼差下來,就是60-100的差距呀,這一般都是演算法差距呀。。。。。。。
我只能說,這題太陰險了。。
你們自己可以去體會體會。
至於這題演算法具體描述,我懶得自己寫了,copy一段(來自@xzyxzy):
於是——怎麼分最後,貼一下**:✔將各個點(結構體)按x的從小到大排序
✔首先運用二分思想將點集合分到最後只剩兩個點的時候
✔然後用這兩點之間的距離更新答案(答案初始化為無限大)
✔然後我們要找到二分的具體實現方案——每次分到一些點時,找到這些點標號的中間(因為點都排好序了,所以其實也就是找到x軸上一條分界線),將整個點的集合大致均分為兩個部分
✔在分界線的右側,將與分界線的距離小於ans的點納入到乙個輔助結構體裡面
✔在分界線的左側,不斷列舉點,列舉到離分界線小於ans的點時,與輔助結構體中的點挨個(等會有解釋)判斷其距離有沒有小於ans,更新ans
注意下用double別掉了精度,然後格式化輸出就好了
然後我的**中,為了避免超時,還是很努力地自己寫了個實數的輸入優化沒想到也過了
#include
#define ll long long
#define inf 0x3f3f3f3f
using
namespace
std;
const
double eps=0.0001;
double read()
if(ch=='.')
}return h+(b*1.000000000)/t;
}struct point
double ans=inf;
void func(int l,int r)
int mid=(l+r)/2;
func(l,mid);
func(mid+1,r);
double line=p[mid].x;
int t=1;
int cnt=0;
for(int i=mid+1;i<=r;i++)
sort(p+1,p+n+1);
func(1,n);
printf("%.4lf",ans);
return
0;}
en 洛谷P1429 平面最近點對(加強版)
核心是分治演算法 分別根據點的 x,y 值進行排序 在 x 軸上劃一道垂線,將點均分成兩半 假設最近點對都在左 右部分,遞迴計算左 右半部分的最短距離 並返回較小值 dis 假設最近點對分別在左右兩個部分,橫跨中心的豎線.中心線為中心,2 dis 為寬度畫乙個矩形,橫跨中心線的最近點對 candid...
題解 洛谷 P1429 平面最近點對(加強版)
p1429 平面最近點對 加強版 分治。左邊的最近距離為 dl 右邊的最近距離為 dr 如何得到整塊的最近距離?我們所需要做的就是計算兩塊之間距離小於 d min dl,dr 的點之間的距離然後取最小值。先把兩塊中距離 mid 的水平距離小於 d 的點加入乙個集合,然後按縱座標排序暴力去計算距離。可...
p1429 平面最近點對
題意 給平面n個點,求最近的兩個點的距離。思路 運用分治思想,對於n個點,可以分成t n 2 t n 2 的規模,分界線是x座標的中位數,假設左邊點集合為s1,右邊點集合為s2,那麼最小值存在於以下三種情況中。1.s1中任意兩點距離的最小距離 2.s2中任意兩點距離的最小距離 3.s1中的點到s2中...