poj1113(凸包)

/*
translation:
	用一條線把若干個點包起來,並且線距離任何一個點的距離都不小於r。求這條線的最小距離是多少?
solution:
	直接求凸包,然後凸包的周長加上一個圓的周長即可。
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;
const int maxn = 50000 + 5;
const double EPS = 1e-10;
const double pi = 3.14159265;

double add(double a, double b)
{
    if(abs(a + b) < EPS * (abs(a) + abs(b)))    return 0;
    return a + b;
}

struct P
{
    double x, y;
    int id;
    P(){}
    P(double x_, double y_):x(x_),y(y_){}

    bool operator < (const P& rhs) const {
        return x < rhs.x || (x == rhs.x && y < rhs.y);
    }

    P operator + (P p) {
        return P(add(x, p.x), add(y, p.y));
    }
    P operator - (P p) {
        return P(add(x, -p.x), add(y, -p.y));
    }
    P operator * (double d) {
        return P(x * d, y * d);
    }
    double dot(P p) {    //內積
        return add(x * p.x, y * p.y);
    }
    double det(P p) {   //外積
        return add(x * p.y, -y * p.x);
    }
} ps[maxn];
int n, r;

double dist(P p, P q)
{
    double ans = (p - q).dot(p - q);
    return sqrt(ans);
}

bool cmp_id(const P& lhs, const P& rhs)
{
    return lhs.id < rhs.id;
}

double graham()
{
    sort(ps, ps + n);
    int k = 0;
    vector<P> res;
    res.resize(n * 2);

    for(int i = 0; i < n; i++) {
        while(k > 1 && (res[k-1] - res[k-2]).det(ps[i] - res[k-1]) <= 0)    k--;
        res[k++] = ps[i];
    }

    for(int i = n - 2, t = k; i >= 0; i--) {
        while(k > t && (res[k-1] - res[k-2]).det(ps[i] - res[k-1]) <= 0)    k--;
        res[k++] = ps[i];
    }
    res.resize(k - 1);

    double len = 0;
    sort(res.begin(), res.end(), cmp_id);
    for(int i = 0; i < res.size()-1; i++)
        len += dist(res[i], res[i+1]);

    int s = res.size();
    len += dist(res[0], res[s-1]);
    return len;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    while(~scanf("%d%d", &n, &r)) {
        for(int i = 0; i < n; i++) {
            cin >> ps[i].x >> ps[i].y;
            ps[i].id = i;
        }

        double tmp = graham() + 2.0 * pi * r;
        int ans = tmp + 0.5;
        cout << ans << endl;
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章