求圆外一点和这些圆的投影。
直接求点和圆的切线与地面的交点,然后按x坐标从小到大排序。然后验证这些点和P的连线是否穿过某个圆,如果穿过,必然不合题意。
中间卡了下精度,如果判断是否穿过某个圆的时候不用eps,我样例都过不去 = =。。。
当然,求和地面的交点可以用解析几何的知识。。。我懒得推。。
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")
#define STOP system("pause")
using namespace std;
const int MAX = 510;
struct point {
double x,y;
void get()
{
scanf("%lf%lf",&x,&y);
}
};
struct circle{point c;double r;};
point p;
circle c[MAX];
point ins[MAX*2];
point l1,l2;
const double eps = 1e-6;
bool dy(double x,double y) { return x > y + eps;} // x > y
bool xy(double x,double y) { return x < y - eps;} // x < y
bool dyd(double x,double y) { return x > y - eps;} // x >= y
bool xyd(double x,double y) { return x < y + eps;} // x <= y
bool dd(double x,double y) { return fabs( x - y ) < eps;} // x == y
double disp2p(point a,point b) // a b 两点之间的距离
{
return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
// 叉积 (三点)
double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向 顺时针是正
{
return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);
}
point Rotate(double ang, point a, point b)
{
b.x -= a.x; b.y -= a.y;
point c;
c.x = b.x * cos(ang) - b.y * sin(ang) + a.x;
c.y = b.x * sin(ang) + b.y * cos(ang) + a.y;
return c;
}
point l2l_inst_p(point u1,point u2,point v1,point v2)
{
point ans = u1;
double t = ((u1.x - v1.x)*(v1.y - v2.y) - (u1.y - v1.y)*(v1.x - v2.x))/
((u1.x - u2.x)*(v1.y - v2.y) - (u1.y - u2.y)*(v1.x - v2.x));
ans.x += (u2.x - u1.x)*t;
ans.y += (u2.y - u1.y)*t;
return ans;
}
void get_point(point p,point c,double r,point &a,point &b)
{
double l = disp2p(c,p);
double ang = asin(r/l);
a = Rotate(ang, p, c);
b = Rotate(-ang, p, c);
a = l2l_inst_p(l1, l2, p, a);
b = l2l_inst_p(l1, l2, p, b);
}
bool cmp(point a,point b)
{
return a.x < b.x;
}
double disp2l(point a,point l1,point l2)
{
return fabs( crossProduct(a,l1,l2) )/disp2p(l1,l2);
}
bool solve(point ins, int n)
{
for(int k=0; k<n; k++)
{
double len = disp2l(c[k].c, p, ins);
if( xy(len,c[k].r) )
return false;
}
return true;
}
int main()
{
int n;
l1.x = l1.y = 0;
l2.x = 10; l2.y = 0;
while( ~scanf("%d", &n) && n )
{
p.get();
int cnt = 0;
for(int i=0; i<n; i++)
{
c[i].c.get();
scanf("%lf", &c[i].r);
get_point(p, c[i].c, c[i].r, ins[cnt], ins[cnt+1]);
cnt += 2;
}
sort(ins, ins+cnt, cmp);
int k = 0;
for(int i=0; i<cnt; i++)
{
if( solve(ins[i], n) )
{
k++;
printf("%.2lf", ins[i].x);
if( k % 2 == 0 )
printf("\n");
else
printf(" ");
}
}
printf("\n");
}
return 0;
}