[poj] 1375 Interval || 圆的切线&和直线的交点

原题

每组数据给出一些圆(障碍物)的圆心和半径,一个点和一条线段,求站在这个点,能开到的线段的部分的左端点和右端点。没有则输出“No View”


相当于求过该点的圆的两条切线,切线外即为可见的地方。
借鉴于这个blog:http://blog.csdn.net/acm_cxlove/article/details/7896110
只要求出两条直线和竖直的夹角,然后通过向量旋转即可得到交点横坐标。

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n;
double r,d;
struct point
{
    double x,y;
    point() {}
    point(double _x,double _y) : x(_x),y(_y) {}
    point operator - (const point &b) const
	{
	    return point(b.x-x,b.y-y);
	}
    double dis()
	{
	    return sqrt(x*x+y*y);
	}
}p,q;
struct edge
{
    double l,r;
    bool operator < (const edge &b) const
	{
	    if (l==b.l) return r<b.r;
	    return l<b.l;
	}
}line[510];

int main()
{
    while (~scanf("%d",&n) && n)
    {
	scanf("%lf%lf",&p.x,&p.y);
	for (int i=0;i<n;i++)
	{
	    scanf("%lf%lf%lf",&q.x,&q.y,&r);
	    d=(p-q).dis();
	    double a=asin(r/d),b=asin((p.x-q.x)/d);
	    double ang1=a+b,ang2=b-a;
	    line[i].l=p.x-p.y*tan(ang1);
	    line[i].r=p.x-p.y*tan(ang2);
	}
	sort(line,line+n);
	double L=line[0].l,R=line[0].r;
	for (int i=1;i<n;i++)
	{
	    if (line[i].l>R)
	    {
		printf("%.2f %.2f\n",L,R);
		L=line[i].l;
		R=line[i].r;
	    }
	    else R=max(line[i].r,R);
	}
	printf("%.2f %.2f\n\n",L,R);
    }
    return 0;
}
posted @ 2017-12-22 22:48  Mrha  阅读(227)  评论(0编辑  收藏  举报