P1429 平面最近点对(加强版)
另附P1257 平面上的最接近点对
题目描述
- 给定平面上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
关于这道题,其实是比较玄学的
思路很简单(简直就是暴力中的极品)
不知道为什么dalao们说要随机旋转
我基本上纯暴力A掉了
以下为方法:
先求第1个点与其余n-1个点的距离;
再求第2个点与其余n-2个点的距离;
…………………………………………
再求第n-1个点与其余1个点的距离;
然后找出最小值,如此的算法复杂度为O(n^2)
核心代码如下:
for(int i=1; i<=n; i++)
for(int j=i; j<=n; j++)
if(i+j<=n)
{
d=sqrt((x[i]-x[j])*(x[i]-x[j])*1.0+(y[i]-y[j])*(y[i]-y[j])*1.0);
if(d<mindist) mindist=d;
}
显然不行
然后就比较玄学了
为了减少枚举量,本少决定只比较每个点后面的150个点
然后莫名AC了
为了再次减少枚举量,本少决定只比较每个点后面的50个点
然后再次莫名AC了
为了再次减少枚举量,本少决定只比较每个点后面的3个点
然后再次莫名AC了
这是一个玄学问题
AC代码如下
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;//流线型头文件
const int Max=200010;
double x[Max],y[Max];
void Qsort(int l,int r)
{
int i,j;
double a,b;
i=l;
j=r;
a=x[(l+r)/2];
while(i<=j)
{
while(x[i]<a) i++;
while(a<x[j]) j--;
if(i<=j)
{
b=x[i]; x[i]=x[j]; x[j]=b;
b=y[i]; y[i]=y[j]; y[j]=b;
i++;
j--;
}
}
if(i<r) Qsort(i,r);
if(l<j) Qsort(l,j);
}//先给x坐标排序
int main()
{
int len;
scanf("%d",&len);
for(int i=1; i<=len; i++)
scanf("%lf%lf",&x[i],&y[i]);
double mindist=99999999999;
Qsort(1,len);
double d;
for(int i=1; i<=len; i++)
for(int j=1; j<=3; j++)//比较每个点后面的3个点
if(i+j<=len)
{
d=sqrt((x[i]-x[i+j])*(x[i]-x[i+j])*1.0+(y[i]-y[i+j])*(y[i]-y[i+j])*1.0);
if(d<mindist) mindist=d;
}//比较
printf("%.4lf
",mindist);
return 0;
}