HDU 6158 计算几何 笛卡尔定理 + 韦达定理

来源:互联网 发布:如何关闭淘宝手机店铺 编辑:程序博客网 时间:2024/04/27 15:30

题目链接


感谢ICPCCamp的题解,链接送上:CCPC 2017网络赛题解

题解已经讲得非常清楚了,补充一点细节吧。

(1).关于笛卡尔定理

对于此题,只需要了解这么一个性质:(来自wiki 用的谷歌翻译,若有偏差还请指出~)

定义一个圆的曲率k=±1r,其中r是其半径。
若平面有两两相切,且有6个独立切点的四个圆,设其曲率为k1,k2,k3,k4(若该圆与其他圆均外切,则曲率取正,否则取负)则其满足性质:

(k1+k2+k3+k4)2=2(k21+k22+k23+k24)

(2).关于韦达定理
对于此题,第一个与已知圆相切的圆的半径非常好求,其半径r3=(r1r2),其中r1是已知圆中较大圆的半径。

故我们现在k1,k2,k3均为已知,代入上面笛卡尔定理的式子便能求解出k4
易发现这是一个关于k4的二次方程,化简为标准形式为:

k242(k1+k2+k3)k4+(k1+k2+k3)22(k21+k22+k23)=0

直接求解是挺困难的,设两个解是x1,x2,利用韦达定理:

x1+x2=2(k1+k2+k3)

因为k4所代表的圆与前三个圆均相切,对于此题,x1,x2就是k3所代表圆左右两个圆的曲率。

对于题目给的图:
k3代表圆1,则x1,x2分别代表圆2和圆3
k3代表圆2,则x1,x2分别代表圆1和圆4

这样我们就可以类似迭代的方式,不断往后递推求解。

这里写图片描述


另外小心精度和时间的问题。
因为N越大,其后面的圆的面积对于答案的贡献几乎可以忽略不计,这时要及时退出循环,避免超时。

亲测,当eps取(1e-13)时跑得最快。

218msAC
代码:

#include<cmath>#include<cstdio>#include<algorithm>using namespace std;typedef long long ll;const double eps = 1e-13;const double PI = acos(-1.0);int main(){    int T;scanf("%d",&T);    while(T--){        int r1,r2,n;        scanf("%d%d%d",&r1,&r2,&n);        if(r1 < r2) swap(r1,r2);        double k1 = -1.0/r1,k2 = 1.0/r2,k3 = 1.0/(r1-r2);        double k4 = k1 + k2 + k3;        double ans = (r1-r2)*(r1-r2);        n--;        for(int i=1 ;i<=n ;i+=2){            double r4 = 1.0/k4;            if(r4*r4 < eps) break;            ans += r4*r4;if(i+1<=n) ans += r4*r4;            double k5 = 2*(k1+k2+k4) - k3;            k3 = k4;k4 = k5;        }        printf("%.5f\n",ans*PI);    }    return 0;}