AOJ - Problem 0010 : Circumscribed Circle of a Triangle
外接円の半径と外心を出力する問題です。
外接円と外心は高校生のときに習った記憶があります。
高校の教科書にも載っていると思います。
三角形が出てくるような幾何の問題では、正弦定理や余弦定理を使うことがあります。
外接円(wikipedia)
三角形クラスを作りました。まだ不完全ですが、内心や内接円の半径、直角三角形の判定などのメンバ関数を
つくると、別の幾何の問題のときに使えるかもしれません。
#include <complex> #include <cstdio> #include <cmath> using namespace std; // 点座標を型とする typedef complex<double> P; // πの定義 #define PI 3.1415926535898 // 許容する誤差ε #define EPS (1e-10) //XY座標 #define X real() #define Y imag() // 三角形クラス class Triangle{ private: //三角形の3点の座標 P a, b, c; //三角形の3辺の長さ double edgeA,edgeB,edgeC; //三角形の3角の大きさ(ラジアン) double angleA,angleB,angleC; //余弦定理から3つの角度を求める関数 double LawOfCosines(double a,double b, double c){ return acos( (b*b+c*c-a*a) / (2.0*b*c) ); } //2つのdouble型の数値が等しいかどうか bool equal(double a, double b){ return (abs( a-b ) < EPS)? true : false ; } public: //コンストラクタ(3つの点と辺と角度を初期化) Triangle(P p1, P p2, P p3){ a = p1; b = p2; c = p3; edgeB = abs(c-a); edgeA = abs(b-c); edgeC = abs(a-b); angleA = LawOfCosines(edgeA,edgeB,edgeC); angleB = LawOfCosines(edgeB,edgeC,edgeA); angleC = LawOfCosines(edgeC,edgeA,edgeB); } double circumscribedCircleRadius(){//外接円の半径を返す return ( edgeA / sin(angleA) / 2.0 ); } double circumscribedCircleX(){//外心(外接円の中心)のX座標を返す double A = sin(2.0*angleA); double B = sin(2.0*angleB); double C = sin(2.0*angleC); return ( (a.X * A + b.X * B + c.X * C) / (A+B+C) ); } double circumscribedCircleY(){//外心(外接円の中心)のY座標を返す double A = sin(2.0*angleA); double B = sin(2.0*angleB); double C = sin(2.0*angleC); return ( (a.Y * A + b.Y * B + c.Y * C) / (A+B+C) ); } }; int main(){ int n; double x1, x2, x3, y1, y2, y3; double r, xp, yp; scanf("%d", &n); for (int i=0 ; i<n ; i++){ scanf("%lf %lf %lf %lf %lf %lf", &x1, &y1, &x2, &y2, &x3, &y3); P a( x1 , y1 ); P b( x2 , y2 ); P c( x3 , y3 ); Triangle Tr(a,b,c); r = Tr.circumscribedCircleRadius(); xp = Tr.circumscribedCircleX(); yp = Tr.circumscribedCircleY(); printf("%.3f %.3f %.3f\n", xp,yp,r); } }