sgu227:The art to the broad masses!(计算几何)

题目大意:
       给出 n 个圆弧,求出它们的交点,如果有重合圆弧,输出Infinity

分析:
       WA 了无数次,各种 WS 的细节,具体看代码吧。

AC code:

#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#define mp make_pair
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define ONLINE_JUDGE
typedef double DB;
const int MAXN = 59;
const DB pi = acos(-1.0);
const DB eps = 1e-8;

int n;
struct pot
{
    DB x, y;
    pot(DB x = 0, DB y = 0):x(x),y(y){}
    void read(){std::cin >> x >> y;}
    void print(){printf("%.3lf %.3lf\n", x, y);}
}a[MAXN], b[MAXN], c[MAXN], o[MAXN];
DB r[MAXN], r2[MAXN];
int fl[MAXN];
pot ans[MAXN*MAXN];
int tot;
DB sqr(DB x) {return x*x;}
bool is_zero(DB k)
{
    return k >= -eps && k <= eps;   
}
int sign(DB k) 
{
    if(k < -eps) return -1;
    else return k > eps;
}
bool operator < (const pot &a, const pot &b)
{
    if(is_zero(a.x-b.x)) return a.y < b.y;
    return a.x < b.x;
}
pot operator - (const pot &a, const pot &b)
{
    return pot(a.x-b.x, a.y-b.y);
}
pot operator + (const pot &a, const pot &b)
{
    return pot(a.x+b.x, a.y+b.y);
}
bool operator == (const pot &a, const pot &b)
{
    return is_zero(a.x-b.x) && is_zero(a.y-b.y);
}
DB dis2(const pot &a, const pot &b)
{
    return sqr(a.x-b.x)+sqr(a.y-b.y);
}
DB dis(const pot &a, const pot &b)
{
    return sqrt(dis2(a, b));
}
DB cross(const pot &a, const pot &b)
{
    return a.x*b.y-a.y*b.x;
}
void insert(const pot &p, const pot &q, const pot &r, int id)
{
    DB x1 = p.x, y1 = p.y, x2 = q.x, y2 = q.y, x3 = r.x, y3 = r.y;
    DB a, b, c, d, e, f, x, y;
    a=2*(x2-x1), b=2*(y2-y1), c=x2*x2+y2*y2-x1*x1-y1*y1;
    d=2*(x3-x2), e=2*(y3-y2), f=x3*x3+y3*y3-x2*x2-y2*y2;
    x=(b*f-e*c)/(b*d-e*a), y=(d*c-a*f)/(b*d-e*a);
    o[id] = pot(x, y), ::r2[id] = dis2(o[id], p), ::r[id] = sqrt(::r2[id]);
}
int inside(const pot &p, int i)
{
    return sign(cross(a[i]-p, b[i]-p))*fl[i];
}
std::pair<pot,pot> get(const pot &p, DB r1, const pot &q, DB r2)
{
    DB m1 = p.x, n1 = p.y, m2 = q.x, n2 = q.y;
    pot ret1, ret2;
    if(!is_zero(m1-m2))
    {
        DB t = (sqr(r1)-sqr(r2)-sqr(m1)+sqr(m2)-sqr(n1)+sqr(n2))/(2*(m2-m1)), k = -(n2-n1)/(m2-m1);
        DB A = sqr(k)+1, B = 2*k*(t-m1)-2*n1, C = sqr(t-m1)+sqr(n1)-sqr(r1);
        DB deita = std::max(0.0, sqr(B)-4*A*C);
        DB y = (-B+sqrt(deita))/(2*A), x = t+k*y;
        ret1 = pot(x, y);
        y = (-B-sqrt(deita))/(2*A), x = t+k*y;
        ret2 = pot(x, y);
    }
    else
    {
        if(n1 < n2) std::swap(m1, m2), std::swap(n1, n2), std::swap(r1, r2);
        DB dy = n1-n2, ty = (sqr(r1)-sqr(r2)+sqr(dy))/(2*dy), tx = sqrt(sqr(r1)-sqr(ty));
        ret1 = pot(m1-tx, n1-ty), ret2 = pot(m1+tx, n1-ty);
    }
    return std::mp(ret1, ret2);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("sgu227.in", "r", stdin);
    freopen("sgu227.out", "w", stdout);
    #endif

    std::ios::sync_with_stdio(0);
    std::cin >> n;
    for(int i = 0; i < n; ++i)
    {
        a[i].read(), b[i].read(), c[i].read();
        insert(a[i], b[i], c[i], i);
        fl[i] = sign(cross(a[i]-c[i], b[i]-c[i]));
    }
    for(int i = 0; i < n; ++i)
        for(int j = i+1; j < n; ++j)
        {
            if(o[i] == o[j] && is_zero(r2[i]-r2[j]))
            {
                if((fl[i] == fl[j] && !inside(a[i], j) && !inside(b[i], j)) || inside(a[i], j) > 0 || inside(b[i], j) > 0 || inside(a[j], i) > 0 || inside(b[j], i) > 0)
                {
                    puts("Infinity");
                    return 0;
                }
                if(!inside(a[i], j)) ans[tot++] = a[i];
                if(!inside(b[i], j)) ans[tot++] = b[i];
                continue;
            }
            DB dij2 = dis2(o[i], o[j]);
            if(sign(dij2-sqr(r[i]+r[j])) > 0 || sign(dij2-sqr(r[i]-r[j])) < 0) continue;
            std::pair<pot, pot> node = get(o[i], r[i], o[j], r[j]);
            if(inside(node.first, i) >= 0 && inside(node.first, j) >= 0) ans[tot++] = node.first;
            if(inside(node.second, i) >= 0 && inside(node.second, j) >= 0) ans[tot++] = node.second;
        }
    std::sort(ans, ans+tot);
    tot = std::unique(ans, ans+tot)-ans;
    std::cout << tot << std::endl;
    for(int i = 0; i < tot; ++i)
        ans[i].print();

    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值