zoj 3806 Incircle and Circumcircle(计算几何:高大上的二分解方程)

给这个题跪了。。。

比赛的时候一直在交,从没停下wa的脚步...

因为这个题目说明了判题的时候是判断能否由输出得到输入

所以我想到这个题一个输入可能对应很多解,但我只需要输出一组可行解就行了

于是自然而然的想到把所有的解抽象成等边三角形,于是就各种WA

后来群里面说应该抽象为等腰三角形,说是什么有可行解就一定有等腰解

但是并没有证明,也不知道他们是怎么想到的...

二分的步骤是:

设三角形两腰为a,底边成为c,内切圆半径r1,外接圆半径r2

二分枚举c,判断何时a同时满足r1,r2

因为有公式S=abc/4r2,现在设等腰三角形高为h

则S=h*c/2,所以h*c/2==a*a*c/4r2

得到a^2 = 2hr2,再由a^2 = h^2 + c^2

可以得到一元二次方程h^2-2hr2+c*c/4 = 0

通过通项公式解出h=r2+sqrt(r2*r2-c*c/4)

进而求出a


接着再通过r1求a:

可以知道h分为两段,一段为r1,另一段长度为sqrt( (a-c/2)*(a-c/2) + r1*r1 ) 

则h = r1+sqrt( (a-c/2)*(a-c/2) + r1*r1 )

进而求出a

再判断 + 二分

代码基本上是看别人的写的:

#include <bits/stdc++.h>
#define LL long long
#define eps 1e-10
using namespace std;

int sgn(double x) {//这个东西的用法很奇葩
    return (x>eps)-(x<-eps);
}

int main(void) {
    double r1, r2, L, R, M, a, c, h;
    while(scanf("%lf%lf", &r1, &r2) != EOF) {
        if(sgn(r2-2*r1) >= 0) {
            L = 0.0, R = sqrt(3.0)*r2;
            while(R-L > eps) {
                c = (L+R) / 2;
                h = r2+( sqrt(r2*r2-c*c/4.0) );
                a = sqrt(h*h+c*c/4.0);
                
                if( sgn(c*c/4.0+pow( r1 + sqrt(r1*r1+(a-c/2.0)*(a-c/2.0)) , 2.0) - a*a) < 0 ) {
                    R = c;
                } else L = c;
            }
            c = L;
            h = r2+( sqrt(r2*r2-c*c/4.0) );
            a = sqrt(h*h+c*c/4.0);
            printf("%.15lf %.15lf %.15lf\n", a, a, c);
        }
        else printf("NO Solution!\n");
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值