hdu 6097 Mindis (高中数学)

高中数学学得贼烂,怎么说呢,如果高三做也许会做,现在就有点要GG的感觉

反演点:二维上反演以一个特定的反演圆为基础:圆心O为反演中心,圆半径为常数k,把点P反演为点P'就是使得OP×OP'=r^2.

题意:

圆心 O 坐标(0, 0), 给定两点 P, Q(不在圆外),满足 PO = QO,

要在圆上找一点 D,使得 PD + QD 取到最小值。


官方题解:

做P点关于圆的反演点P',OPD与ODP'相似,相似比是|OP| : r。

Q点同理。

极小化PD+QD可以转化为极小化P'D+Q'D。

当P'Q'与圆有交点时,答案为两点距离,否则最优值在中垂线上取到。

时间复杂度 O(1)O(1)

hdu 6097 Mindis (高中数学)_第1张图片

hdu 6097 Mindis (高中数学)_第2张图片

为什么要选择反演点呢,因为如果选择相似三角形已知的比例只有r/d,刚好符合反演点,只能说反演点在同心圆中被用到的多了,有了这么一个名字,如果没有这个反演点的名字也要这么搞,因为已知的条件,只有角相等,r和d的长度。。。。


#include 
#define eps 1e-8
void work() {
    double r, x1, y1, x2, y2;
    scanf("%lf%lf%lf%lf%lf", &r, &x1, &y1, &x2, &y2);
    double d0 = sqrt(pow(x1, 2) + pow(y1, 2));
    if (fabs(d0) < eps) {
        printf("%.7f\n", 2 * r);
        return;
    }
    double k = r * r / (d0 * d0);
    double x3 = x1 * k, x4 = x2 * k, y3 = y1 * k, y4 = y2 * k;
    double mx = (x3+x4)/2, my = (y3+y4)/2, ans;
    double d = sqrt(pow(mx,2)+pow(my,2));
    if (d <= r) {
        double dist = sqrt(pow(x3 - x4, 2) + pow(y3 - y4, 2));
        ans = dist * d0 / r;
    }
    else {
        double kk = r / d;
        double smx = mx * kk, smy = my * kk;
        ans = 2 *sqrt(pow(smx - x1, 2) + pow(smy - y1, 2));
    }
    printf("%.7f\n", ans);
}
int main() {
    int T;
    scanf("%d", &T);
    while (T--) work();
    return 0;
}


你可能感兴趣的:(ACM-数学方法)