求平面内最近的点


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <cstring>
#include <sstream>
#include <map>
#include <stack>
#include <queue>
#include <ctime>
#include <cstdlib>
#define MAX 2000000000
using namespace std;

struct node{  //结构体
     double x,y;  //  x,y坐标
     int id;  // 该变量用来表示  不同的集合
     node(double x = -1,double y = -1,int id = 0){
        this -> x = x;
        this -> y = y;
        this -> id = id;
     };
    bool operator < (const node &t1){  //重载  “<"
        return this -> x < t1.x;
    }
};
node *total;
double getdistance(node t1,node t2){  //求两点之间的距离
    //cout << "---\n";
    if(t1.x == t2.x && t2.y == t1.y)
        return 0;
    double v;
    double x = (t1.x - t2.x) * (t1.x - t2.x);
    double y = (t1.y - t2.y) * (t1.y - t2.y);
    v = sqrt(x + y);
    return v;
}

bool com(const node t1,const node t2){
    return t1.y < t2.y;
}

//left_set: 左边集合  right_set: 右边集合。  d: 左,右集合中最小的距离。  mid :  分界点。 x:  分界点的x值。
double mid_dist(int start,int mid, int end,int d,double x){
    node *s = new node[end - start + 1];
    int cnt = 0;
    for(int i = start; i <= end; i++)
        if(abs(x - total[i].x) <= d)
            s[cnt++] = total[i];
    sort(s,s + cnt,com);
    double len = MAX; //表示最小距离
    int t = 0;
    for(int i = 0; i < cnt; i++){
        t = 0;
        for(int j = i + 1; j < cnt && t <= 6 && abs(i - j) <= d; j++){
            if(total[i].id != total[j].id){
                t++;
                len = min(len,getdistance(total[i],total[j]));
            }
        }
    }
    delete []s;
    return len;
}
double minimumDist(int start,int end){  //求最短路径,   参数为排序后的所有点的集合。
    if(start == end) return MAX;    //小于2,直接返回最大值
    if(end - start == 1){   //等于2,则计算路径长度
        if(total[start].id != total[end].id)  //不能为同一个集合。  否则也返回最大值
            return getdistance(total[start],total[end]);
        else
            return MAX;
    }
   // vector<node> left_set,right_set; //平衡后的左边 和 右边
    double left_dist,right_dist;  //左边的最小距离    右边的最小距离
   // int len = (start + end) / 2;
//划分左右

    int mid = (start + end) / 2;;
   // cout << start << "  " << mid << "  " << end << endl;
左边的最小距离    右边的最小距离
    left_dist = minimumDist(start,mid);
    right_dist = minimumDist(mid + 1, end);

//左右中比较小的一个。
    double d = min(left_dist,right_dist);

//mid_dist() : 求中间的距离;
    d = min(d,mid_dist(start,mid,end,d,total[mid].x));
  //  cout << left_dist << "   " << right_dist << "   " << d << endl;
    return d;
}
int main(){
    int n,k;
    cin >> n;
    while(n--){
            cin >> k;
            double x,y;
            int i = 0;
            total = new node[k * 2];
            for(; i < k; i++){
                cin >> x >> y;
                total[i] = node(x,y,1);
            }

            for(; i < 2 * k; i++){
                cin >> x >> y;
                total[i] = node(x,y,2);
            }
            sort(total,total + i);
            double dist = minimumDist(0,i - 1);
            printf("%.3f\n",dist);
            delete []total;
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值