反演变换
- 反演变换适用于题目中存在多个圆/直线之间的相切关系的情况。利用反演变换的性质,在反演空间求解问题,可以大幅简化计算。
具体讲解:- 反演变换-OIwiki
模板来源:
题目集:
关于反演变换的补充:
1 . 要注意直线过反演点的特殊情况。
2 . 不过反演中心的直线反演之后内外侧会置换。那么直线和一个相切的圆的反演有两种情况:
-
直线过反演中心:反演后直线还是过反演中心
-
直线不过反演中心:如果原本反演中心和圆心在直线的同一侧,反演后两心位于异侧。反之,反演后两心位于同侧
板子:
struct circle{
point o;
double r;
};
point ptp(point a, point p, double r) // 保证a和p不重合,否则会出现除以零的情况
{
point v = a - p;
double len = r * r / get_dis(p, a);
return p + norm(v) * len;
}
circle ctc(circle c, point p, double r) // 保证c不过p点
{
circle res;
double t = get_dis(p, c.o);
double x = r * r / (t - c.r), y = r * r / (t + c.r);
res.r = (x - y) / 2;
double s = (x + y) / 2;
res.o = p + norm(c.o - p) * s;
return res;
}
void ctl(circle c, point & a, point & b, point p, double r) // 保证c过p点
{
point v = c.o - p;
double d = r * r / (2 * c.r);
a = p + norm(v) * d;
b = a + rotate(a, pi / 2);
}
circle ltc(point a, point b, point p, double r) // 保证l不过点p
{
double d = dis_to_line(a, b, p);
d = r * r / d;
circle res;
res.r = d / 2;
point v;
if(area(a, b, p) > 0) v = rotate(b - a, -pi/2);
else v = rotate(a - b, -pi/2);
res.o = p + norm(v) * res.r;
return res;
}