zoukankan      html  css  js  c++  java
  • 过圆外一点与圆的切线方程()

    Intervals
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 4046   Accepted: 1180

    Description

    In the ceiling in the basement of a newly open developers building a light source has been installed. Unfortunately, the material used to cover the floor is very sensitive to light. It turned out that its expected life time is decreasing dramatically. To avoid this, authorities have decided to protect light sensitive areas from strong light by covering them. The solution was not very easy because, as it is common, in the basement there are different pipelines under the ceiling and the authorities want to install the covers just on those parts of the floor that are not shielded from the light by pipes. To cope with the situation, the first decision was to simplify the real situation and, instead of solving the problem in 3D space, to construct a 2D model first. 
    Within this model, the x-axis has been aligned with the level of the floor. The light is considered to be a point light source with integer co-ordinates [bx,by]. The pipes are represented by circles. The center of the circle i has the integer co-ordinates [cxi,cyi] and an integer radius ri. As pipes are made from solid material, circles cannot overlap. Pipes cannot reflect the light and the light cannot go through the pipes. You have to write a program which will determine the non-overlapping intervals on the x-axis where there is, due to the pipes, no light from the light source. 

    Input

    The input consists of blocks of lines, each of which except the last describes one situation in the basement. The first line of each block contains a positive integer number N < 500 expressing the number of pipes. The second line of the block contains two integers bx and by separated by one space. Each of the next N lines of the block contains integers cxi, cyi and ri, where cyi + ri < by. Integers in individual lines are separated by one space. The last block consists of one line containing n = 0.

    Output

    The output consists of blocks of lines, corresponding to the blocks in the input(except the last one). One empty line must be put after each block in the output. Each of the individual lines of the blocks in the output will contain two real numbers, the endpoints of the interval where there is no light from the given point light source. The reals are exact to two decimal places and separated by one space. The intervals are sorted according to increasing x-coordinate.

    Sample Input

    6
    300 450
    70 50 30
    120 20 20
    270 40 10
    250 85 20
    220 30 30
    380 100 100
    1
    300 300
    300 150 90
    1
    300 300
    390 150 90
    0

    Sample Output

    0.72 78.86
    88.50 133.94
    181.04 549.93
    
    75.00 525.00
    
    300.00 862.50

    题意:在天花板上给出一盏灯,下面放有n个圆柱形钢管,问下面有几段阴影部分,且输出阴影段的两个端点
    分析:对于每个圆形,和圆外一点P,P与该圆的两条切线与X轴的交点就是阴影段的两个端点,先求出所有圆形对应的阴影段,因为有重合的,然后一遍扫描即可求出结果:
    #include"stdio.h"
    #include"string.h"
    #include"stdlib.h"
    #include"queue"
    #include"algorithm"
    #include"string.h"
    #include"string"
    #include"math.h"
    #include"vector"
    #include"stack"
    #include"map"
    #define eps 1e-4
    #define inf 0x3f3f3f3f
    #define M 609
    #define PI acos(-1.0)
    using namespace std;
    struct node//二维点坐标
    {
        double x,y;
        node(){};
        node(double xx,double yy)
        {
            x=xx;
            y=yy;
        }
        node operator+(node b)
        {
            return node(x+b.x,y+b.y);
        }
        node operator-(node b)
        {
            return node(x-b.x,y-b.y);
        }
        node operator*(double b)
        {
            return node(x*b,y*b);
        }
        double operator*(node b)
        {
            return x*b.x+y*b.y;
        }
        double operator^(node b)
        {
            return x*b.y-y*b.x;
        }
    }P;
    struct Circle//定义圆心和半径
    {
        node center;
        double r;
    }p[M];
    struct Line//定义直线一般式的三个参数ABC
    {
         double A,B,C;
    };
    double len(node a)
    {
        return sqrt(a*a);
    }
    double dis(node a,node b)
    {
        return len(a-b);
    }
    double cross(node a,node b,node c)
    {
        return (b-a)^(c-a);
    }
    double dot(node a,node b,node c)
    {
        return (b-a)*(c-a);
    }
    Circle Inver(node p,double R,Circle c)
    {
        Circle ret;
        double pc=dis(p,c.center);
        ret.r=R*R/2*(1/(pc-c.r)-1/(pc+c.r));
        double pc0=R*R/(pc+c.r)+ret.r;
        ret.center.x=p.x+(pc0/pc)*(c.center.x-p.x);
        ret.center.y=p.y+(pc0/pc)*(c.center.y-p.y);
        return ret;
    }
    Line line(node a,node b)
    {
        Line l;
        l.A=b.y-a.y;
        l.B=a.x-b.x;
        l.C=b.x*a.y-a.x*b.y;
        return l;
    }
    node Ratate(node a,double rad)//向量逆时针旋转rad的角度
    {
        return node(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
    }
    Line PointCutCircle(node p,Circle c,int clock)//过圆外一点p且与圆的切线,clock代表两个不同的切线
    {
        Line ret;
        node she;
        she=c.center-p;
        double pc=dis(c.center,p);
        double rad=asin(c.r/pc);
        if(clock==-1)//逆时针旋转
        {
            node she1=Ratate(she,rad);
            ret.A=she1.y;
            ret.B=-she1.x;
            ret.C=she1.x*p.y-p.x*she1.y;
        }
        if(clock==1)//顺时针旋转
        {
            node she1=Ratate(she,-rad);
            ret.A=she1.y;
            ret.B=-she1.x;
            ret.C=she1.x*p.y-p.x*she1.y;
        }
        return ret;
    }
    struct st
    {
        double l,r;
    }s[M];
    int cmp(st a,st b)
    {
        if(a.l!=b.l)
            return a.l<b.l;
        else
            return a.r<b.r;
    }
    int main()
    {
        int n,i,kk=0;
        while(scanf("%d",&n),n)
        {
            scanf("%lf%lf",&P.x,&P.y);
            for(i=1;i<=n;i++)
                scanf("%lf%lf%lf",&p[i].center.x,&p[i].center.y,&p[i].r);
            for(i=1;i<=n;i++)
            {
                Line L1=PointCutCircle(P,p[i],1);
                Line L2=PointCutCircle(P,p[i],-1);
                s[i].l=-L1.C/L1.A;
                s[i].r=-L2.C/L2.A;
            }
            if(kk)
                printf("
    ");
            kk++;
            sort(s+1,s+n+1,cmp);
            double L=s[1].l;
            double R=s[1].r;
            for(i=2;i<=n;i++)
            {
                if(s[i].l<=R)
                {
                    R=max(R,s[i].r);
                }
                else
                {
                    printf("%.2lf %.2lf
    ",L,R);
                    L=s[i].l;
                    R=s[i].r;
                }
            }
            printf("%.2lf %.2lf
    ",L,R);
        }
        return 0;
    }
    


  • 相关阅读:
    SAP ABAP 开发中常用的方法总结
    安装sap帮助文档
    spring成神之路第七篇:DI依赖注入之手动注入
    spring成神之路第三篇:Spring容器基本使用及原理(ApplicationContext接口获取bean的4种方式)
    spring成神之路第九篇:dependon到底是干什么的?
    spring成神之路第十篇:primary可以解决什么问题?
    spring成神之路第四篇:xml中bean定义详解
    spring成神之路第六篇:玩转bean scope,避免跳坑里
    spring成神之路第一篇:为何要学spring
    spring成神之路第五篇:创建bean实例的方式
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348116.html
Copyright © 2011-2022 走看看