HDU6158 The Designer 【圆的反演】

先把内外两个初始的圆反演成两条平行直线
然后里面的圆肯定都是这两条平行直线之间相切的圆反演回去的圆啦。
直接一个一个的算就好了。题目给的N很大,但是当反演回去的圆的面积小到一定程度可忽略,跳出循环就好。。

自己写的东西一开始常数超级大而且好像会RE之类的。。
也是调了一年的题。。最后还是借鉴了网上的写法。。。计算几何好难啊。。。

代码:

#include <bits/stdc++.h>
using namespace std;
#define sq(x) ((x)*(x))
double refr;
#define reflect(x) (sq(refr)/(x))
const double PI = acos(-1.0);
const double eps = PI*1e-13;

int t, N;
double R[2];
int tot = 0;
double dlt, length, high, tlen, r, area_, area;
int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%lf%lf%d", &R[0], &R[1], &N);
        if (R[0] > R[1]) swap(R[0], R[1]);
        refr = 2. * R[1];
        dlt = (reflect(2*R[0]) - reflect(2*R[1]))/2.;
        length = sq(refr + dlt);
        high = 0.;
        area = sq(R[1] - R[0]); --N;
        tlen, r, area_;
        while (N) {
            high += dlt*2;
            tlen = sqrt(length+sq(high));
            r = (reflect(tlen-dlt)-reflect(tlen+dlt))/2.;
            area_ = sq(r);
            if (area_ < eps) break;
            area += area_; --N;
            if (!N) break;
            area += area_; --N;
        }
        printf("%.5f\n", area * PI);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值