第一次写博客先来个签到题试一下水doge:
提示:纯小白,大佬勿喷(qwq
- 一周掌握蓝桥杯入门算法(1/7)
题面
题目描述
给定平面上 nnn 个点,找出其中的一对点的距离,使得在这 nnn 个点的所有点对中,该距离为所有点对中最小的。
输入格式
第一行一个整数 nnn,表示点的个数。
接下来 nnn 行,每行两个实数 x,yx,yx,y ,表示一个点的行坐标和列坐标。
输出格式
仅一行,一个实数,表示最短距离,四舍五入保留 444 位小数。
输入输出样例
输入 #1
3
1 1
1 2
2 2
输出 #1
1.0000
说明/提示
数据规模与约定
对于 100% 的数据,保证 1≤n≤1041 \leq n \leq 10^41≤n≤104,0≤x,y≤1090 \leq x, y \leq 10^90≤x,y≤109,小数点后的数字个数不超过 666。
--------------------------------------华丽的分割线-------------------------------------
Let s Do It
方法一:喜闻乐见 暴力美学
先求第一个点和后面每个点的距离
再求第二个点和后面每个点的距离
再求第三个点和后面每个点的距离
...
求倒数第二个点到倒数第一个点的距离
每次求出来之后对比一下答案和每个距离的大小
如果有比答案还小的距离就把答案踢出去,换成它
这就搞完了!(doge)
时间复杂度 O(n^2) 数据最多只到10000,管那么多干嘛qwq能过就好(doge)
具体实现:
用vector向量数组把每个点存入进去,考虑到每个点有横坐标和纵坐标两个变量,于是再用stl库中的pair来给他俩牵红线:make_pair(x,y),然后存入vector中后来依次比较实现上述的算法就o了个k,容易想也容易实现;
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int>>a;
#define inf 0x5fffff
long double dis(int x1,int y1,int x2,int y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main()
{
long double ans=inf;
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a.push_back(make_pair(x,y));
}
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
long double d=dis(a[i].first,a[i].second,a[j].first,a[j].second);
if(ans>=d)ans=d;
}
}
cout<<fixed<<setprecision(4)<<ans<<endl;
}
方法二:分而治之(分治法)
1.按照x/y坐标升序排序(直接用库中的sort函数搞定)O(nlogn)根据下标进行分割成两个集合
2.递归寻找两个集合中的最近的点对,取最小值;
问题:有可能一个点在a集合一个点在b集合,他俩距离最小
3.那就先取两个集合中的最小值min,跟边界点左右两个点x坐标的平均值midx
划分出以一个[mid-min,mid+min],最小距离点对应该在这中间,所以用这个区间左半边的点跟右半边的点
tips:
#include<bits/stdc++.h>
using namespace std;
struct point
{
double x,y;
}p[100086];
int n,t[100086];
bool cmp(const point &A,const point &B)
{
if(A.x==B.x)
return A.y<B.y;
else
return A.x<B.x;
}
bool cmps(const int &a,const int &b)
{
return p[a].y<p[b].y;
}
double distance(int i,int j)
{
return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
}
double merge(int left,int right)
{
double dis=2<<20;
if(left==right)
return dis;
if(left+1==right)
return distance(left,right);
int mid=(left+right)>>1;
double d1=merge(left,mid);
double d2=merge(mid+1,right);
dis=min(d1,d2);
int k=0;
for(int i=left;i<=right;i++)
if(fabs(p[i].x-p[mid].x)<=dis)
t[k++]=i;
sort(t,t+k,cmps);
for(int i=0;i<k;i++)
for(int j=i+1;j<k&&p[t[j]].y-p[t[i]].y<dis;j++)
dis=min(dis,distance(t[i],t[j]));
return dis;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
scanf("%lf %lf",&p[i].x,&p[i].y);
sort(p,p+n,cmp);
printf("%.4lf\n",merge(0,n-1));
return 0;
}