Kattis - doors Doors

题目:

Alex is a circle of radius  R R. Well, life as a circle is not easy. If he were a point, moving around and passing through doors would be effortless. But now he has to carefully inspect the surroundings before making every move.

\includegraphics[width=.6\textwidth ]{figure}

Alex’s is initially at position  (0,y) (0,y∞), where  y y∞ is much bigger than the width of the corridor  w w. Alex wants to meet Bob, who happens to be living to the far right of the corridor (may as well be somewhere at  (x,w/2) (x∞,w/2), where  x x∞ is much bigger than  ). The lengths of the two doors are  . It is guaranteed that  w ℓ≤w, so that door B will never hit the opposite side of the wall.

You are given  T T scenarios. In each scenario, the angles  A A and  B B are given (both are radians in the range  [0,π] [0,π]). Find the largest  rR r≤R such that when Alex’s radius is shrunk to  r r, he can reach Bob while avoiding the obstacles (walls and doors).

Formally, Alex when shrunk to radius  r r can reach Bob if and only if there exists a (continuous) curve from  (0,y) (0,y∞) to  (x,w/2) (x∞,w/2) such that the minimal distance between a point on the curve and a point on an obstacle (a wall or a door) is at least  r r. In particular, if  r=0 r=0 then Alex will be able to reach Bob.

Input

The first line of input consists of three integers,  R R , and  w w ( 1,w,R100 1≤ℓ,w,R≤100and  w ℓ≤w). The second line of input consists of an integer  T T ( 1T10000 1≤T≤10000), the number of scenarios to follow. Each of the next  T T lines consists of a pair of real numbers, representing angles  A A and  B B (in radians). The numbers are given with exactly  4 4 decimal places.

Output

For each scenario, output the required answer on a separate line. Your answer will be accepted if its absolute or relative error (compared to the judge’s answer) is at most  105 10−5.

Sample Input 1Sample Output 1
10 6 8
4
0.0000 0.0000
3.1415 0.0000
1.0472 0.0000
1.0472 1.5708
0.000000000
3.000000000
2.598079885
1.000000000
题意:如图,alex的半径小于等于R,有两扇门(绿线和蓝线),输入他的角度,alex 和bob都分别离门无限远,问,是否alex可以穿过缝隙到达bob的位置

,求出能穿过的alex的最大半径。

分析:分情况讨论点与直线距离,保证能通过时,选取最大半径。最后不要忘记再R范围内。讨论比较繁琐,要仔细细心。直接上代码。




代码:

#include <cstdio>
#include <cmath>
#include <iostream>
#define PI 3.141592654
using namespace std;
struct line//直线ax+by+c=0, 记录a,b,c的值
{
  double a, b, c;
};
line zhixian(double x1, double y1, double x2, double y2)//计算a ,b, c
{
    line q;
    if(x1 == x2) {
            q.a = 1;
            q.b = 0;
            q.c = -x1;
    }
    else if(y1 == y2){
           q.a = 0;
           q.b = 1;
           q.c = -y1;
    }
    else{
        q.a = y2-y1;
        q.b = x1-x2;
        q.c = (x2-x1)*y1 - (y2-y1)*x1;
    }
    return q;
}
double juli2(double x1, double y1, double x2, double y2)//两点间距离
{
     return sqrt((y2-y1)*(y2-y1)+(x2-x1)*(x2-x1));
}
bool judge(double x1, double y1, double x2, double y2, double x3, double y3)//点到直线的距离中,与直线的交点可能不在线段(门)上,通过三点能否组成钝角三角形判断
{
    double a = juli2(x1, y1, x2, y2);
    double b = juli2(x1, y1, x3, y3);
    double c = juli2(x2, y2, x3, y3);
    if(c*c + a*a - b*b < 0) return true;
    return false;
}
double juli(double x, double y, line q)//计算点到直线距离
{
    return fabs(q.a*x + q.b*y + q.c) / sqrt(q.a*q.a + q.b*q.b);
}

int main()
{
    double R, l, w; cin >> R >> l >> w;
    int t; cin >> t;
    while(t--)
    {
        double p1, p2;
        cin >> p2 >> p1;
        double Mx, My, Nx, Ny;
            Mx = l - l*cos(p1);
            My = l*sin(p1);
            Nx = l - l*cos(p2);
            Ny = l*sin(p2)+w;
        double Ax = 0, Ay = w;
        double Bx = l, By = w;
        double Cx = l, Cy = 0;
        double ans = 0;

        if(p2 >= PI/2 && p1 < PI/2){
             if(judge(Bx,By,Mx,My,Cx,Cy))
             {
                 double d3 = juli2(Bx, By, Mx, My);
                 ans = min(d3, l);
             }
             else
             {
                double d = juli(Bx, By, zhixian(Cx, Cy, Mx, My));
                ans = min(d, l);
             }
        }

        else if(p2 >= PI/2 && p1 >= PI/2){
             double d = w - My;
             ans = min(d, l);
        }

        else if(p2 < PI/2 && p1 < PI/2){
             double d1, d2, d3;
             if(judge(Mx,My,Bx,By,Nx,Ny)) {
                double d4 = juli2(Mx, My, Bx, By);
                d1 = d4;
             }
             else {
                d1 = juli(Mx, My, zhixian(Bx, By, Nx, Ny));
             }

             if(judge(Cx,Cy,Mx,My,Bx,By)) {
                 double d6 = juli2(Bx, By, Mx, My);
                 d2 = d6;
             }
             else {
                d2 = juli(Bx, By, zhixian(Mx, My, Cx, Cy));
             }

             if(judge(Ax,Ay,Nx,Ny,Bx,By)) {
                double d9 = juli2(Ax, Ay, Nx, Ny);
                d3 = d9;
             }
             else {
                d3 = juli(Ax, Ay, zhixian(Bx, By, Nx, Ny));
             }
            ans = min(d1, d2);
            ans = min(ans, d3);
        }

        else if(p2 < PI/2 && p1 >= PI/2){
             double d2 = w - My;
             double d1;
             if(judge(Ax,Ay,Nx,Ny,Bx,By)) {
                  double d4 = juli2(Ax, Ay, Nx, Ny);
                  d1 = d4;
             }
             else {
                d1 = juli(Ax, Ay, zhixian(Bx, By, Nx, Ny));
             }
             ans = min(d1, d2);
        }
        ans /= 2;
        if(ans > R) ans = R;
        printf("%.9f\n", ans);
    }
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值