読者です 読者をやめる 読者になる 読者になる

AOJ0010 - Circumscribed Circle of a Triangle

計算するだけなんですけど,色々と面倒臭かった.

AOJ0010

参考:kanetaiの二次記憶装置

各点から円の中心までの距離(つまり半径)が全て等しいことを考える.

各点を { A(x_1, y_1)} { B(x_2, y_2)} { C(x_3, y_3)} と置く.
また中心の座標を{ P(x_p, y_p)} と置く.

半径が等しいということは

{ | \vec{PA}| = | \vec{PB}| = | \vec{PC}|}

これらを連立方程式として解けば{ x_p}{ y_p}が求まる.

連立方程式は以下のようになる.

{
\begin{cases}
\; 2(x_1 - x_2)x_p + 2(y_1 - y_2)y_p = x_1^2 + y_1^2 - x_2^2 - y_2^2 \\
\; 2(x_1 - x_3)x_p + 2(y_1 - y_3)y_p = x_1^2 + y_1^2 - x_3^2 - y_3^2
\end{cases}}

行列を用いて,

\begin{pmatrix} 2(x_1 - x_2) & 2(y_1 - y_2) \\ 2(x_1 - x_3) & 2(y_1 - y_3) \\ \end{pmatrix}

逆行列

\begin{pmatrix} x_1^2 + y_1^2 - x_2^2 - y_2^2 \\ x_1^2 + y_1^2 - x_3^2 - y_3^2 \\ \end{pmatrix}

の積を求めればよい.

また,半径の長さは先程の { | \vec{PA}| = | \vec{PB}| = | \vec{PC}|} どれか一つに代入して求める.

コード

#define sq(x) ((x) * (x))

signed main()
{
  int n;
  scanf("%d", &n);

  while (n--){
    double x1, y1, x2, y2, x3, y3;
    scanf("%lf%lf%lf%lf%lf%lf", &x1, &y1, &x2, &y2, &x3, &y3);

    double a = 2 * (x1 - x2), b = 2 * (y1 - y2),
           c = 2 * (x1 - x3), d = 2 * (y1 - y3);
    double e = sq(x1) + sq(y1) - sq(x2) - sq(y2),
           f = sq(x1) + sq(y1) - sq(x3) - sq(y3);

    double x = (1 / (a * d - b * c)) * (d * e - b * f),
           y = (1 / (a * d - b * c)) * (-c * e + a * f);

    double r = sqrt(sq(x - x1) + sq(y - y1));
    printf("%.3f %.3f %.3f\n", x, y, r);
  }

  return 0;
}