poj 1375 Intervals(计算圆的切线)

该博客介绍了POJ 1375题目的解决方法,主要涉及计算圆的切线。通过极角坐标系,博主解析了如何确定圆心到点的直线极角,以及计算切点和求阴影部分的过程。文章提到了可能存在的精度问题,并分享了简化问题的假设(n<100)。最后,提供了代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Intervals
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 3109 Accepted: 907

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

Source

题目:http://poj.org/problem?id=1375

题意:给你一个灯和一些水管的切面,也就是圆,求这些圆在地面上形成的阴影

分析:由于题目的各种限制,所有就成了简单的计算切线问题,我这里是用极角来做的,首先求出圆心到点这条直线的极角,然后求出切点到圆心,和点到圆心的夹角,一减一加就得到两个极角,然后圆心向着两个极角移动r的距离,就是切点了,最后就是按比例求切线在x轴上的交点。。。

PS:发现极角好好用啊,就是不知道会不会出现精度问题,反正还没出现过^_^

还有这题我一厢情愿的认为n<100,re了啊= =

代码:

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int mm=555;
struct seg
{
    double l,r;
}g[mm];
double cx,cy,r,bx,by,a1,a2;
int i,j,n;
bool cmp(seg a,seg b)
{
    return a.l<b.l;
}
double Dis(double sx,double sy,double tx,double ty)
{
    return sqrt((sx-tx)*(sx-tx)+(sy-ty)*(sy-ty));
}
double solve(double x,double y)
{
    return x+y*(x-bx)/(by-y);
}
int main()
{
    while(scanf("%d",&n),n)
    {
        scanf("%lf%lf",&bx,&by);
        for(i=0;i<n;++i)
        {
            scanf("%lf%lf%lf",&cx,&cy,&r);
            a1=atan2(by-cy,bx-cx);
            a2=acos(r/Dis(cx,cy,bx,by));
            g[i].l=solve(cx+r*cos(a1-a2),cy+r*sin(a1-a2));
            g[i].r=solve(cx+r*cos(a1+a2),cy+r*sin(a1+a2));
            if(g[i].l>g[i].r)swap(g[i].l,g[i].r);
        }
        sort(g,g+n,cmp);
        i=0;
        while(i<n)
        {
            cx=g[i].l;
            cy=g[i++].r;
            while(i<n&&g[i].l<=cy)cy=max(cy,g[i++].r);
            printf("%.2lf %.2lf\n",cx,cy);
        }
        puts("");
    }
    return 0;
}


㈠ 点的基本运算 1. 平面上两点之间距离 1 2. 判断两点是否重合 1 3. 矢量叉乘 1 4. 矢量点乘 2 5. 判断点是否在线段上 2 6. 一点饶某点旋转后的坐标 2 7. 矢量夹角 2 ㈡ 线段及直线的基本运算 1. 点与线段的关系 3 2. 点到线段所在直线垂线的垂足 4 3. 点到线段的最近点 4 4. 点到线段所在直线的距离 4 5. 点到折线集的最近距离 4 6. 判断是否在多边形内 5 7. 矢量夹角余弦 5 8. 线段之间的夹角 5 9. 判断线段是否相交 6 10.判断线段是否相交但不交在端点处 6 11.线段所在直线的方程 6 12.直线的斜率 7 13.直线的倾斜角 7 14.点关于某直线的对称点 7 15.判断两条直线是否相交及直线交点 7 16.判断线段是否相交,如果相交返回交点 7 ㈢ 多边形常用算法模块 1. 判断多边形是否简单多边形 8 2. 检查多边形顶点的凸凹性 9 3. 判断多边形是否凸多边形 9 4. 多边形面积 9 5. 判断多边形顶点的排列方向,方法一 10 6. 判断多边形顶点的排列方向,方法二 10 7. 射线法判断点是否在多边形内 10 8. 判断点是否在凸多边形内 11 9. 寻找点集的graham算法 12 10.寻找点集凸包的卷包裹法 13 11.判断线段是否在多边形内 14 12.简单多边形的重心 15 13.凸多边形的重心 17 14.肯定在给定多边形内的一个点 17 15.从多边形外一点出发到该多边形的切线 18 16.判断多边形的核是否存在 19 ㈣ 的基本运算 1 .点是否在内 20 2 .不共线的三点所确定的 21 ㈤ 矩形的基本运算 1.已知矩形三点坐标,第4点坐标 22 ㈥ 常用算法的描述 22 ㈦ 补充 1.两关系: 24 2.判断是否在矩形内: 24 3.点到平面的距离: 25 4.点是否在直线同侧: 25 5.镜面反射线: 25 6.矩形包含: 26 7.两交点: 27 8.两公共面积: 28 9. 和直线关系: 29 10. 内切: 30 11. 切点: 31 12. 线段的左右旋: 31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值