• UVa 10180 Rope Crisis in Ropeland!


    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=41&page=show_problem&problem=1121

    题意:给出两点坐标,用一条最短的线(曲线或者直线)连接起来,坐标系中原点处有一个半径为R的圆,连线不能穿过这个圆。

    分析:

    这题我WA了好几次,原因是把double的坐标搞成int了,o(╯□╰)o

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 
     5 const double PI = acos( -1.0 );
     6 
     7 struct point
     8 {
     9     double x, y;
    10 };
    11 
    12 point O;  //坐标原点
    13 
    14 double Get_Dist( point &a, point &b )    //计算两点间距离
    15 {
    16     return sqrt( (a.x - b.x)*(a.x - b.x) + (a.y - b.y )*(a.y - b.y) );
    17 }
    18 
    19 double Get_Angle( double a, double b, double c )  //余弦定理求角度
    20 {
    21     return acos( (b*b + c*c - a*a) / (2*b*c) );
    22 }
    23 
    24 bool check( point &m, point &n, double x, double y )  //判断坐标( x, y )是否在点 m, n 之间
    25 {
    26     double minx = m.x < n.x ? m.x : n.x;
    27     double maxx = m.x > n.x ? m.x : n.x;
    28     double miny = m.y < n.y ? m.y : n.y;
    29     double maxy = m.y > n.y ? m.y : n.y;
    30     return ( x > minx && x <= maxx && y >= miny && y <= maxy );
    31 }
    32 
    33 bool Judge( point &m, point &n, double &R )           //判断是否需要绕过圆
    34 {
    35     if ( m.x == n.x )                                 //特判与y轴平行的线
    36     {
    37         if ( abs(m.x) >= R ) return true;
    38         else
    39         {
    40             if ( m.y * n.y > 0 ) return true;
    41             else return false;
    42         }
    43     }
    44     else if ( m.y == n.y )                             //特判与x轴平行的线
    45     {
    46         if ( abs(m.y) >= R ) return true;
    47         else
    48         {
    49             if ( m.x * n.x > 0 ) return true;
    50             else return false;
    51         }
    52     }
    53 
    54     double A = n.y - m.y;                              //两点连成的直线,求直线方程一般式,计算A, B, C
    55     double B = m.x - n.x;
    56     double C = (n.x - m.x) * m.y - (n.y - m.y) * m.x;
    57     double dis = abs(C)/ sqrt( A*A + B*B );            //原点到直线的距离
    58     if ( dis >= R ) return true;
    59     else
    60     {
    61         double kkk = (-A) / B;
    62         double bbb = (-C) / B;
    63         double xx = ( -bbb ) / ( kkk + 1.0 / kkk );
    64         double yy = ( (-1.0) / kkk ) * xx;
    65         if ( check( m, n, xx, yy ) ) return false;     //如果线段穿过圆
    66         else return true;                              //如果线段不穿过圆
    67     }
    68 }
    69 
    70 int main()
    71 {
    72     int T;
    73     double R;
    74     point A, B;
    75     O.x = 0;
    76     O.y = 0;
    77     scanf( "%d", &T );
    78     while ( T-- )
    79     {
    80         scanf( "%lf%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y, &R );
    81 
    82         if ( Judge(A, B, R) )                             //如果不需要绕过圆
    83             printf( "%.3f\n", Get_Dist(A, B) );
    84         else                                              //如果需要绕过圆
    85         {
    86             double L1 = Get_Dist(A, O);
    87             double L2 = Get_Dist(B, O);
    88             double LL1 = sqrt( L1*L1 - R*R );
    89             double LL2 = sqrt( L2*L2 - R*R );
    90             double angle = Get_Angle( Get_Dist(A, B), L1, L2 ) - acos( R/L1 ) - acos( R/L2 );
    91             double ans = LL1 + LL2 + R * angle;
    92             printf( "%.3f\n", ans );
    93         }
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    SQL Server 2005 学习笔记之触发器简介[转]
    什么是BCD 码
    关于C# 中的Attribute 特性
    也谈Asp.net 中的身份验证
    SQL Server 2005 创建分区表
    使用SerialPort 对象实现串口拨号器通信[下]
    子角色权限的实现
    SQL Server 中,实现 varbinary 与 varchar 类型之间的数据转换
    TSQL 常用排名函数
    关于ASP.NET 将数据导出成Excel 的总结[中]
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/2649587.html
Copyright © 2020-2023  润新知