在平面给出许多半径不一的圆,求一条直线最多能穿过多少个圆。
求出每两个圆间的四条公切线,并保存角度值,并用1和-1标记这四条直线何时是进两圆范围,何时是出两圆范围。然后按斜率排序切线,扫一遍,通过标记计算什么时候通过的圆最多。
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const int N = 2010;
const double pi = acos(-1.0);
inline int sig(double x)
{
return (x > eps) - (x < -eps);
}
typedef struct Point
{
double x, y;
Point () {}
Point (double _x, double _y):
x(_x), y(_y) {}
void in()
{
scanf("%lf%lf", &x, &y);
}
double dis()
{
return sqrt(x * x + y * y);
}
}Vector;
Vector operator -(const Vector &a, const Vector &b)
{
return Vector(a.x - b.x, a.y - b.y);
}
Vector operator +(const Vector &a, const Vector &b)
{
return Vector(a.x + b.x, a.y + b.y);
}
struct Circle
{
Point o;
double r;
Circle () {}
Circle (Point _o, double _r):
o(_o), r(_r) {}
void in()
{
o.in();
scanf("%lf", &r);
}
};
Circle cc[N];
struct Line
{
double ang;
int t;
Line () {}
Line (double _ang, int _t):
ang(_ang), t(_t) {}
void out()
{
printf("%.2lf %d\n", ang, t);
}
bool operator <(const Line &a) const
{
return (sig(ang - a.ang) == 0 ? t > a.t : sig(ang - a.ang) < 0);
}
};
Line ss[N<<2];
int cnt, n;
void tan(Circle a, Circle b)
{
double d = (a.o - b.o).dis();
double rdif = a.r - b.r;
double rsum = a.r + b.r;
double base = atan2((b.o).y - (a.o).y, (b.o).x - (a.o).x);
double ang = acos(rdif / d);
ss[cnt++] = Line(base + ang, -1);
ss[cnt++] = Line(base - ang, 1);
if(sig(d - rsum) > 0)
{
ang = acos(rsum / d);
ss[cnt++] = Line(base + ang, 1);
ss[cnt++] = Line(base - ang, -1);
}
return ;
}
void solve()
{
int ans = 0;
for(int i = 0; i < n; i++)
{
cnt = 0;
for(int j = 0; j < n; j++)
{
if(i == j)
continue;
tan(cc[i], cc[j]);
}
sort(ss, ss + cnt);
//printf("cnt == %d i == %d\n", cnt, i);
//for(int j = 0; j < cnt; ++j) ss[j].out();
int ma = 0;
for(int j = 0; j < cnt; j++)
{
if(ss[j].t == 1)
ma++;
else
ma--;
ans = max(ma, ans);
}
}
printf("%d\n", ans + 1);
return ;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i = 0; i < n; ++i)
cc[i].in();
solve();
}
return 0;
}