HDU 4667 计算几何 (乱搞)

题意 : 不说了自己看
题解 : 做这个题就像发现了新大陆,因为发现了一个计算几何的乱搞的方法,就是如果让你找一个点的话我们就可以把一个圆或者一个线段等分成若干份就好了,等分成若干份然后暴力 或者加点什么优化这类的东西,这个题就是这样啊.

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;

const int maxn = 55;
const double eps = 1e-8;
const double INF = 1e30;
const int di = 2505;
const double PI = 3.141592653589793;
const int N = 3e5 + 5;
struct point {
    double x,y;
}p[N];
int n,m;
int cnt = 0;
int tot ;
struct circle {
    point o;
    double r;
}c[maxn];
point poly[N];
point init;
struct res {
    point a,b,c;
}r[maxn];

int sgn (double x) {
    if (fabs (x) <= eps) return 0;
    return x > 0 ? 1 : -1;
}


double cross (point a,point b,point c) {
    return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}

double dist (point a,point b) {
    return sqrt ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

bool cmp (const point a,const point b) {
    if (sgn (cross (init,a,b)) == 0) return dist (init,a) < dist (init,b);
    return sgn (cross (init,a,b)) > 0;
}

void tubao () {
    tot = 0;
    poly[++ tot] = p[1],poly[++ tot] = p[2];
    for (int i = 3;i <= cnt; ++ i) {
        while (tot >= 2) {
            point p1 = poly[tot];
            point p2 = poly[tot - 1];
            point p3 = p[i];
            if (sgn (cross (p2,p1,p3)) <= 0) tot --;
            else break;
        }
        poly[++ tot] = p[i];
    }
}


int main () {
    while (~scanf ("%d%d",&n,&m)) {
        cnt = tot = 0;
        for (int i = 1;i <= n; ++ i) {
            scanf ("%lf%lf%lf",&c[i].o.x,&c[i].o.y,&c[i].r);
            point temp = c[i].o;
            double R = c[i].r;
            for (int j = 0;j <= di; ++ j) {
                p[++ cnt] = {temp.x + R * cos (2 * PI * double (j) / di),temp.y + R * sin (2 * PI * double (j) / di)};
            }
        }
        for (int i = 1;i <= m; ++ i) {scanf ("%lf%lf%lf%lf%lf%lf",&r[i].a.x,&r[i].a.y,&r[i].b.x,&r[i].b.y,&r[i].c.x,&r[i].c.y);
            p[++ cnt] = r[i].a,p[++ cnt] = r[i].b,p[++ cnt] = r[i].c;
        }
        double ans = 0;
        for (int i = 1;i <= cnt; ++ i) {
            if (p[i].y < p[1].y || (sgn (p[i].y - p[1].y) == 0 && p[i].x < p[1].x)) swap (p[i],p[1]);
        }
        init = p[1];
        sort (p + 1,p + cnt + 1,cmp);
        tubao ();
        poly[tot + 1] = poly[1];
        for (int i = 1;i <= tot; ++ i) {
            ans += dist (poly[i],poly[i + 1]);
        }
        printf("%.10f\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值