Template - the nearest point on the plane

This is the correct algorithm, but the complexity may be stuck to the \ (O (the n-^ 2) \) , plus 15/30 limit near the point of matching up to each point most of the words complexity can guarantee, and most to do it again increases the probability of correct, how was the card I did not get out from start to finish it is random.

#include<bits/stdc++.h>
using namespace std;

const double PI = acos(-1.0);

struct Point {
    double x, y;
} p[200000 + 5];

int n;

inline double RandomDouble() {
    return 1.0 * rand() / RAND_MAX;
}

inline bool cmp(const Point &a, const Point &b) {
    return a.x < b.x;
}

inline double dis(const Point &a, const Point &b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

double Calc(const double &A, double d) {
    double x0 = -1e9 + 2e9 * RandomDouble(), y0 = -1e9 + 2e9 * RandomDouble(); //随机弄一个旋转原点
    double cosA = cos(A), sinA = sin(A);
    double xc = -x0 * cosA + y0 * sinA + x0;
    double yc = -x0 * sinA - y0 * cosA + y0;
    //利用图形学的知识加速
    for(int i = 1; i <= n; i++) {
        double x = p[i].x, y = p[i].y;
        //p[i].x = (x - x0) * cosA - (y - y0) * sinA + x0;
        //p[i].y = (x - x0) * sinA + (y - y0) * cosA + y0;
        p[i].x = x * cosA - y * sinA + xc;
        p[i].y = x * sinA + y * cosA + yc;
    }
    sort(p + 1, p + 1 + n, cmp);

    for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= n /*&& j <= i + 15*/ && p[j].x - p[i].x < d; j++)
            d = min(d, dis(p[i], p[j]));
    }
    return d;
}

int main() {
    srand(time(0));

    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lf%lf", &p[i].x, &p[i].y);

    double d = 1e36;
    d = Calc(RandomDouble() * 2.0 * PI, d);
    //d = Calc(RandomDouble() * 2.0 * PI, d);
    printf("%.4f\n", d);
    return 0;
}

Divide and conquer algorithm, although each layer which are sorted, but not many actually selected point.

#include<bits/stdc++.h>
using namespace std;

const double INF = 1e36;

const int MAXN = 200000;

int n, tmp[MAXN];
struct Point {
    double x, y;
} S[MAXN + 5];

bool cmpx(const Point &a, const Point&b) {
    return a.x < b.x;
}

bool cmpidy(const int &a, const int &b) {
    return S[a].y < S[b].y ;
}

inline double min(const double &a, const double &b) {
    return a < b ? a : b;
}

inline double dist(const int &i, const int &j) {
    return sqrt((S[i].x - S[j].x) * (S[i].x - S[j].x) + (S[i].y - S[j].y) * (S[i].y - S[j].y));
}

double merge(int left, int right) {
    double d = INF;
    if(left == right)
        return d ;
    if(left + 1 == right)
        return dist(left, right);
    int mid = left + right >> 1;
    double d1 = merge(left, mid) ;
    double d2 = merge(mid + 1, right) ;
    d = min(d1, d2);
    int i, j, k = 0;
    for(i = left; i <= right; i++)
        if(fabs(S[mid].x - S[i].x) <= d)
            tmp[++k] = i;
    sort(tmp + 1, tmp + k + 1, cmpidy);
    for(i = 1; i <= k; i++)
        for(j = i + 1; j <= k && S[tmp[j]].y - S[tmp[i]].y < d; j++) {
            double d3 = dist(tmp[i], tmp[j]);
            if(d > d3)
                d = d3;
        }
    return d;
}

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lf%lf", &S[i].x, &S[i].y);
    sort(S + 1, S + n + 1, cmpx);
    printf("%.4f\n", merge(1, n));
    return 0;
}

Random algorithm more efficient, but can not guarantee the accuracy because only took up the 10 points, if there could be removed this card to T, but from the origin to the rotation angle of the rotation is completely random, a few more test times may be on the line, if not, then you can rest assured Calc more than a few times.
If, then 20 points after taking up should be a limit, and if the 20 points are not too prefer to re-Calc once.

#include<bits/stdc++.h>
using namespace std;

const double PI = acos(-1.0);

struct Point {
    double x, y;
} p[200000 + 5];

int n;

inline double RandomDouble() {
    return 1.0 * rand() / RAND_MAX;
}

inline bool cmp(const Point &a, const Point &b) {
    return a.x < b.x;
}

inline double dis(const Point &a, const Point &b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

double Calc(const double &A) {
    double x0 = -10.0 + 20.0 * RandomDouble(), y0 = -10.0 + 20.0 * RandomDouble(); //随机弄一个旋转原点
    for(int i = 1; i <= n; i++) {
        double x = p[i].x, y = p[i].y, xn, yn;
        xn = (x - x0) * cos(A) - (y - y0) * sin(A) + x0 ;
        yn = (x - x0) * sin(A) + (y - y0) * cos(A) + y0 ;
        p[i].x = xn;
        p[i].y = yn;
    }
    sort(p + 1, p + 1 + n, cmp);

    double d = 1e36;
    for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= n && j <= i + 10 && p[j].x - p[i].x < d; j++)
            d = min(d, dis(p[i], p[j]));
    }
    return d;
}

int main() {
    srand(time(0));

    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lf%lf", &p[i].x, &p[i].y);

    printf("%.4f\n", Calc(RandomDouble() * 2.0 * PI));
    return 0;
}

Like this?

#include<bits/stdc++.h>
using namespace std;

const double PI = acos(-1.0);

struct Point {
    double x, y;
} p[200000 + 5];

int n;

inline double RandomDouble() {
    return 1.0 * rand() / RAND_MAX;
}

inline bool cmp(const Point &a, const Point &b) {
    return a.x < b.x;
}

inline double dis(const Point &a, const Point &b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

double Calc(const double &A, double d) {
    double x0 = -1e9 + 2e9 * RandomDouble(), y0 = -1e9 + 2e9 * RandomDouble(); //随机弄一个旋转原点
    for(int i = 1; i <= n; i++) {
        double x = p[i].x, y = p[i].y, xn, yn;
        xn = (x - x0) * cos(A) - (y - y0) * sin(A) + x0 ;
        yn = (x - x0) * sin(A) + (y - y0) * cos(A) + y0 ;
        p[i].x = xn;
        p[i].y = yn;
    }
    sort(p + 1, p + 1 + n, cmp);

    for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= n && j <= i + 15 && p[j].x - p[i].x < d; j++)
            d = min(d, dis(p[i], p[j]));
    }
    return d;
}

int main() {
    srand(time(0));

    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lf%lf", &p[i].x, &p[i].y);

    double d = 1e36;
    d = Calc(RandomDouble() * 2.0 * PI, d);
    d = Calc(RandomDouble() * 2.0 * PI, d);
    printf("%.4f\n", d);
    return 0;
}

Constant bit card, there are a lot of excess floating-point operations. If the limit up to 15 points after removing the correctness can be guaranteed, but the complexity may explode, but this way you need only count it once.

#include<bits/stdc++.h>
using namespace std;

const double PI = acos(-1.0);

struct Point {
    double x, y;
} p[200000 + 5];

int n;

inline double RandomDouble() {
    return 1.0 * rand() / RAND_MAX;
}

inline bool cmp(const Point &a, const Point &b) {
    return a.x < b.x;
}

inline double dis(const Point &a, const Point &b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

double Calc(const double &A, double d) {
    double x0 = -1e9 + 2e9 * RandomDouble(), y0 = -1e9 + 2e9 * RandomDouble(); //随机弄一个旋转原点
    double cosA = cos(A), sinA = sin(A);
    double xc = -x0 * cosA + y0 * sinA + x0;
    double yc = -x0 * sinA - y0 * cosA + y0;
    //利用图形学的知识加速
    for(int i = 1; i <= n; i++) {
        double x = p[i].x, y = p[i].y, xn, yn;
        //p[i].x = (x - x0) * cosA - (y - y0) * sinA + x0;
        //p[i].y = (x - x0) * sinA + (y - y0) * cosA + y0;
        p[i].x = x * cosA - y * sinA + xc;
        p[i].y = x * sinA + y * cosA + yc;
    }
    sort(p + 1, p + 1 + n, cmp);

    for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= n /*&& j <= i + 15*/ && p[j].x - p[i].x < d; j++)
            d = min(d, dis(p[i], p[j]));
    }
    return d;
}

int main() {
    srand(time(0));

    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lf%lf", &p[i].x, &p[i].y);

    double d = 1e36;
    d = Calc(RandomDouble() * 2.0 * PI, d);
    //d = Calc(RandomDouble() * 2.0 * PI, d);
    printf("%.4f\n", d);
    return 0;
}

Guess you like

Origin www.cnblogs.com/Inko/p/11516098.html