はまやんはまやんはまやん

hamayanhamayan's blog

Fifa and Fafa [Codeforces Round #465 C]

http://codeforces.com/contest/935/problem/C

半径R, 中心(x1,y1)の円Cと(円の外かもしれない)頂点P(x2,y2)がある。
これについて以下の条件を満たす円C'の半径と中心を答えよ。

  • 円C'は円Cの内部にある
  • 円C'は頂点Pを含まない
  • 円C'は上の2条件を満たす中で半径が最大

解法

http://codeforces.com/contest/935/submission/35487154

「d := 円Cの中心と点Pとの距離」とする。
 
まず、コーナーケースを説明しておこう。
1つ目は頂点Pが円Cの中心である場合である(d == 0だがソース中ではd<1e-9のこと。1e-9はeps)
この場合では半径はR/2の円が最大で書ける。
中心は適当な所に取ればいいが、(X1+ R/2, Y1)がお手軽。
2つ目は頂点Pが円Cの外にある場合である(R≦d)
この場合では円C'は円Cと全く同じになる。
 
それ以外の場合では円Cに内接し、頂点Pと接するように円C'を書いてやると、半径は(R+d)/2となる。
中心は(X2 + (X1-X2)*R/d, Y2+(Y1-Y2)*R/d)となる。
これはベクトルを使って求めているが、元々は「(X2,Y2) + (X1-X2,Y1-Y2) * R / d」

double R, X1, Y1, X2, Y2;
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> R >> X1 >> Y1 >> X2 >> Y2;

    double d = sqrt((X1 - X2)*(X1 - X2) + (Y1 - Y2)*(Y1 - Y2));

    if(d < 1e-9) printf("%.10f %.10f %.10f\n", X1 + R / 2, Y1, R / 2);
    else if (R <= d) printf("%.10f %.10f %.10f\n", X1, Y1, R);
    else {
        double r = (R + d) / 2;
        double x = X2 + (X1 - X2) * r / d;
        double y = Y2 + (Y1 - Y2) * r / d;
        printf("%.10f %.10f %.10f\n", x, y, r);
    }