UVA 10180 Rope Crisis in Ropeland!【判断圆与直线位置】

题目大意:自行百度。

解题策略:


  

首先判断AB所在直线是否与圆相交:
1,不相交:直接计算AB距离即可。

2,相交:
          (1)这里有wa点,还需判断AB线段是否与圆相交,若不想交计算同1;

                     判断方法:若三角形ABO中角A或角B为钝角,线段与圆不相交;

          (2)若AB线段与圆相交,

                     最终答案:ansL = AD + 弧CD + BC,

                     第一步:AD,BC由勾股定理求得;

                     第二步:弧CD = 圆心角COD(弧度制)*半径

                     第三步:利用余弦定理求出角BOA,,角AOD,角B0C ————  角COD = 角BOA - 角AOC-角BOC;

                     由第三步逐步向上操作,既得答案。

3,注意事项:
         (1)计算几何一定要细心再细心,尤其是复杂运算,一定要注意;

         (2)C/C++三角函数针对弧度制操作,注意必要转换;

                     


/*
   UVA 10180 Rope Crisis in Ropeland!
   AC by J_Dark
   ON 2013/5/14 19:52
   Time 0.582s
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-20;

struct p{
    double x, y;
    void Set(double a, double b){ x = a; y = b;}
    double Ditance(p t){
       return sqrt( (t.x-x)*(t.x-x) + (t.y-y)*(t.y-y) );
    }
}A, B, C, D, O;
double rad, AB, AD, AO, BO, BC;

void Input(){
    double x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2 >> rad;
    A.Set(x1, y1);
    B.Set(x2, y2);
    AB = A.Ditance(B);
    O.Set(0, 0);
}

bool isSpecialNI(){
    AO = A.Ditance(O);
    BO = B.Ditance(O);
    if(AO*AO + AB*AB - BO*BO < eps || AB*AB + BO*BO - AO*AO  < eps)
       return true;
    return false;
}

double aCos(double a, double b, double c){
    return (a*a + b*b - c*c) / (2*a*b);  //这个表达式分母忘记加括号,结果调了一下午T-T
}

double compute(){
    double BOC, AOD, COD, BOA;
    BC = sqrt(BO*BO - rad*rad);
    AD = sqrt(AO*AO - rad*rad);
    BOA = acos(aCos(BO, AO, AB));
    BOC = acos(aCos(BO, rad, BC));
    AOD = acos(aCos(AO, rad, AD));
    COD = (BOA - BOC - AOD);
    return COD*rad + BC + AD;
}

void Solve(){
    double AA, BB, CC, dd, ansL;
    bool f1;
    if(fabs(A.x - B.x) < eps){  //线段斜率不存在
        dd = fabs(A.x);
    }
    else{ //线段斜率存在
        AA = (B.y - A.y)/(B.x - A.x);
        BB = -1;
        CC = A.y - A.x*AA;
        dd = fabs(CC/sqrt(AA*AA + BB*BB));
    }
    if(dd < rad){  //圆与线段所在直线相交
        if(isSpecialNI()){   //线段与圆不相交
            f1 = false;
        }
        else{//线段与圆相交 正式进入运算
            f1 = true;
            ansL = compute();
        }
    }
    else f1 = false;
    if(!f1){ //圆与线段不相交
        ansL = AB;
    }
    printf("%.3lf\n", ansL);
}

int main(){
    int testCase;
    while(cin >> testCase)
    {
        while(testCase--)
        {
           Input();
           Solve();
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值