EOJ 1189/POJ 1113/HDU 1348 Wall

題目簡介


給定平面上的n個點及半徑r,求圓的周長與凸包周長之和。

說明


記錄一下Graham求凸包的模板。

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

const double PI = acos(-1.0);
const int maxn = 1005;

struct point {int x, y;}p[maxn];
int s[maxn], top;

inline int cross(point p0, point p1, point p2)
{
    return (p1.x-p0.x) * (p2.y-p0.y) - (p1.y-p0.y) * (p2.x-p0.x);
}

inline double dis(point p1, point p2)
{
    return sqrt((p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y));
}

inline bool cmp(point p1, point p2)
{
    int c = cross(p[0], p1, p2);
    if (c > 0) return 1;
    else if (!c && dis(p[0], p1) < dis(p[0], p2)) return 1;
    return 0;
}

inline void graham(int n)
{
    s[0] = 0;
    if (n == 1) top = 0;
    else
    {
        s[1] = top = 1;
        if (n == 2) return;
        for (int i = 2; i < n; ++i)
        {
            while (top && cross(p[s[top-1]], p[s[top]], p[i]) <= 0)
                --top;
            s[++top] = i;
        }
    }
}

int main()
{
    int n, r;
    double ans;
    while (cin >> n >> r)
    {
        scanf("%d%d", &p[0].x, &p[0].y);
        point p0;
        p0.x = p[0].x; p0.y = p[0].y;
        int k = 0;
        for (int i = 1; i < n; ++i)
        {
            scanf("%d%d", &p[i].x, &p[i].y);
            if ((p0.y>p[i].y) || ((p0.y==p[i].y)&&(p0.x>p[i].x)))
            {
                p0.x = p[i].x;
                p0.y = p[i].y;
                k = i;
            }
        }
        p[k] = p[0];
        p[0] = p0;
        sort(p+1, p+n, cmp);
        graham(n);
        ans = 2 * PI * r;
        for (int i = 0; i <= top; ++i)
            ans += dis(p[s[i]], p[s[(i+1) % (top+1)]]);
        printf("%d\n", (int)(ans+0.5));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章