作者:手机用户2602904645 | 来源:互联网 | 2023-09-05 11:11
这道题《算法导论》和《编程之美》都有详细的讲解
分治思想:先把n个点按x坐标排序,然后求左边n/2个和右边n/2个的最近距离,最后合并。
合并要考虑 最近点对 的其中一个点在左边,另一个在右边的情况。
如上图,只需考虑[x-minDist,x+minDist]的这段区域minDist*(2*minDist)的矩形区域,这样一个区域最多只有八个点(反推),所以只用搜索按坐标y排序后紧随其后的7个点即可。0和1,2,3,4....;1和2,3,4...
这里有详细的证明点击打开链接
总的算法复杂度为O(nlogn)
hdu上面这道题用cin读取数据TLE了,改为scanf就AC了
#include
#include
#include
#include
#include
using namespace std;const int maxn=100005;
struct Point{
public:double x,y;
};
Point v[maxn];
int ind[maxn];
bool cmpx(const Point &p1,const Point &p2){return p1.x}bool cmpy(int i1,int i2){return v[i1].y}double dis(const Point& p1, const Point& p2){return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
double min(double a,double b)
{return a}
double devide(int l,int r)
{if(r&#61;&#61;1&#43;l)return dis(v[r],v[l]);if(r&#61;&#61;2&#43;l)return min(min(dis(v[l],v[l&#43;1]),dis(v[l&#43;1],v[r])),dis(v[l],v[r]));int mid&#61;(l&#43;r)/2;int c&#61;0;double minDis&#61;min(devide(l,mid),devide(mid&#43;1,r));for(int i&#61;l;i<&#61;r;&#43;&#43;i){if(v[i].x<&#61;v[mid].x&#43;minDis&&v[i].x>&#61;v[mid].x-minDis){ind[c&#43;&#43;]&#61;i;}}sort(ind,ind&#43;c,cmpy);for(int i&#61;0;i&#61;minDis)break;minDis&#61;min(minDis,dis(v[ind[i]],v[ind[j]]));}}return minDis;
}int main()
{//freopen("in.txt","r",stdin);int n;while(cin>>n&&n){double x,y;for(int i&#61;0;i}