【GCJ2009B】Min Perimeter

【GCJ2009B】Min Perimeter:

给你一个整数坐标的点集,询问点集中最小的三角形周长是多少。退化的三角形也是允许的(面积为0)。
0 < n <= 100000

题解:

没有结合所学的知识,于是没有想出来。

记得以前学过平面最近点对。

利用分治法,和一个结论,2d*d的矩形里,每个点相互的距离不超过d,最多可以摆6个点。

这题也可以分治,并且大胆猜测结论,可能的点数也是常数级别的,于是就行了。

Code:

#include<cmath>
#include<cstdio>
#include<algorithm>
#define db double
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;

const int N = 1e5 + 5;

int n, d[N], st, en;
struct node {
    int x, y;
} a[N];
db p;

db dis(node a, node b) {return sqrt((db) (a.x - b.x) * (a.x - b.x) + (db) (a.y - b.y) * (a.y - b.y));}
int cmp(node a, node b) {return a.x < b.x;}
int cmp2(node a, node b) {return a.y < b.y;}
db solve(int x, int y, int z) {return dis(a[x], a[y]) + dis(a[x], a[z]) + dis(a[y], a[z]);}

void dg(int x, int y) {
    if(x == y) return;
    int m = x + y >> 1;
    dg(x, m); dg(m + 1, y);
    int u = a[m].x;
    sort(a + x, a + y + 1, cmp2);
    st = 1; en = 0;
    fo(i, x, y) {
        while(st <= en && a[i].y - a[d[st]].y > p) st ++;
        if(a[i].x >= u - p / 2 && a[i].x <= u + p / 2) {
            fo(j, st, en - 1) fo(k, j + 1, en)
                p = min(p, solve(i, d[j], d[k]));
            d[++ en] = i;
        }
    }
}

int main() {
    scanf("%d", &n);
    fo(i, 1, n) scanf("%d %d", &a[i].x, &a[i].y);
    sort(a + 1, a + n + 1, cmp);
    p = 1e18; dg(1, n);
    printf("%.10lf", p);
}

猜你喜欢

转载自blog.csdn.net/cold_chair/article/details/81018504