POJ 1375 Intervals 光源投影【平面几何】

<题目链接>

 <转载于>

题目大意:

给一个光源点s,给一些圆,源点和s相切会形成阴影,求每一段阴影在横轴上的区间。

解题分析:

这道其实不需要点与圆切线的板子来求解,完全可以根据角度和线段长度之间的关系计算。

解此题的方法就是,先单独对每一个圆研究,算出它们各自在横轴上的投影区间,然后,再求出这些区间的并,把每一段区间输出即可。


                                            这里写图片描述                                

当然,我们应该要注意到,点与圆的位置关系不只有这一种情况,还一种情况是,圆的圆形没有超过垂线,但是圆的圆心X+R超过了垂线,但是,经过简单证明发现,其实这两种情况都可以用一个表达式来表示,所以下面的代码只用写一种形式。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 503


struct Ln   //投影的区间
{
    double l, r;//区间的左右端点横坐标
    bool operator<(const Ln &b)const
    {
        return l < b.l;
    }
}lns[MAXN];
int N;   //水管总数


int main()
{
    while (~scanf("%d", &N) && N)
    {
        int Lx, Ly;     //light 灯的坐标
        scanf("%d%d", &Lx, &Ly);

        for (int p = 0; p < N; p++) {
            int Ox, Oy, r;
            scanf("%d%d%d", &Ox, &Oy, &r);//input
            double OL = sqrt(double(Ox - Lx)*(Ox - Lx) + (Oy - Ly)*(Oy - Ly));
            double alpha = asin((Lx - Ox) / OL);//∠OLC
            double beta = asin(r / OL);//∠OLA
            lns[p].l = Lx - Ly * tan(alpha + beta);
            lns[p].r = Lx - Ly * tan(alpha - beta);       
        }


        sort(lns, lns + N);
        double L = lns[0].l, R = lns[0].r;//初始化第一个区间      
        for (int p = 1; p < N; p++) {
            if (lns[p].l > R) {   
                printf("%.2lf %.2lf
", L, R);//output//输出上一个
                L = lns[p].l, R = lns[p].r;//初始化下一个
            }
            else
                R = max(lns[p].r, R);    //由于会出现长区间包含短区间的情况 因而需要比较大小
        }
        printf("%.2lf %.2lf

", L, R);    //output//输出最后一个大区间,这里不要忘记
    }
    return 0;
}

2018-08-01

原文地址:https://www.cnblogs.com/00isok/p/9404498.html