题目大意:给定一个三角形ABC,求三角形的Exocenter。Exocenter定义:对三角形ABC三边作正方形,得到正方形ADEB,BJHC,CFGA,连接DG,EJ,FH,取DG、EJ、FH的中点L、M、N,直线LA、BM、CN的交点即为Exocenter.
解题思路:求出直线LA和MB,用高斯消元法求交点O。先用垂直条件、等长条件和钝角条件求D、G、E、J的坐标,再求L、M的坐标。
注意:浮点误差,两垂直直线和三种情况。
代码如下:
1 #include <cstdio> 2 #include <cmath> 3 #include <utility> 4 #include <climits> 5 #include <vector> 6 using namespace std; 7 8 //typedef pair<double, double> Cor; 9 10 struct Cor{ 11 double x; 12 double y; 13 Cor(double x_ = 0, double y_ = 0) : x(x_), y(y_) {} 14 Cor operator-(const Cor &other) const { 15 return Cor(x - other.x, y - other.y); 16 } 17 18 Cor operator+(const Cor &other) const { 19 return Cor(x + other.x, y + other.y); 20 } 21 Cor operator/(const double &num) const { 22 return Cor(x / num, y / num); 23 } 24 static Cor midCor(const Cor &cor1, const Cor &cor2) { 25 return (cor1 + cor2) / 2; 26 } 27 }; 28 29 const double error_range = 0.0000001; 30 bool doubleEqual(const double & a, const double &b) { 31 return fabs(a - b) <= error_range; 32 } 33 34 bool doubleLarger(const double &a, const double &b) { 35 return a - b > error_range; 36 } 37 38 bool doubleSmaller(const double &a, const double &b) { 39 return b - a > error_range; 40 } 41 42 double dot(const Cor &A, const Cor &B) { 43 return A.x * B.x + A.y * B.y; 44 } 45 46 Cor getExtrianglePoint(const Cor &B, const Cor &A, const Cor &C) { 47 Cor one, two; 48 // 如果原直线平行于x轴 49 if (A.y == B.y) { 50 one.x = A.x; 51 one.y = A.y + fabs(B.x - A.x); 52 two.x = A.x; 53 two.y = A.y - fabs(B.x - A.x); 54 } else if (A.x == B.x) { 55 one.y = A.y; 56 one.x = A.x + fabs(B.y - A.y); 57 two.y = A.y; 58 two.x = A.x - fabs(B.y - A.y); 59 } else { 60 one.x = A.x + fabs(B.y - A.y); 61 one.y = A.y - (B.x - A.x) * (one.x - A.x) / (B.y - A.y); 62 two.x = A.x - fabs(B.y - A.y); 63 two.y = A.y - (B.x - A.x) * (two.x - A.x) / (B.y - A.y); 64 } 65 66 if (doubleSmaller(dot(one - A, C - A), 0 )) { 67 return one; 68 } else if (doubleSmaller(dot(two - A, C - A), 0)) { 69 return two; 70 } else { 71 printf("error "); 72 return Cor(); 73 } 74 75 } 76 77 vector<double> Gauss(double (*matrix)[3], const int &n) { 78 vector<int> select(n - 1); 79 vector<bool> visited(n - 1, false); 80 bool notSingle = false; 81 for (int i = 0; i < n - 1; ++i) { 82 int maximum_num; 83 double maximum = 0; 84 for (int j = 0; j < n - 1; ++j) { 85 if (!visited[j] && doubleLarger(fabs(matrix[j][i]), fabs(maximum))) { 86 maximum_num = j; 87 maximum = matrix[j][i]; 88 } 89 } 90 if (doubleEqual(maximum, 0)) { 91 notSingle = true; 92 break; 93 } 94 visited[maximum_num] = true; 95 select[i] = maximum_num; 96 for (int j = 0; j < n - 1; ++j) { 97 if (j == maximum_num) continue; 98 if (doubleEqual(matrix[j][i], 0)) continue; 99 double coefficient = -1 * matrix[j][i] / maximum; 100 for (int k = i; k < n; ++k) { 101 matrix[j][k] = matrix[maximum_num][k] * coefficient + matrix[j][k]; 102 } 103 } 104 } 105 vector<double> ans; 106 if (notSingle) return ans; 107 for (int i = 0; i < select.size(); ++i) { 108 ans.push_back(matrix[select[i]][n - 1] / matrix[select[i]][i]); 109 } 110 return ans; 111 } 112 113 double GM[2][3]; 114 115 116 117 int main() { 118 int n; 119 Cor A, B, C; 120 scanf("%d", &n); 121 while (n--) { 122 scanf("%lf%lf%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y, &C.x, &C.y); 123 Cor D = getExtrianglePoint(B, A, C); 124 Cor G = getExtrianglePoint(C, A, B); 125 Cor L = (D + G) / 2; 126 Cor E = getExtrianglePoint(A, B, C); 127 Cor J = getExtrianglePoint(C, B, A); 128 Cor M = (E + J) / 2; 129 130 if (doubleEqual(L.x, A.x)) { 131 GM[0][0] = 1; 132 GM[0][1] = 0; 133 GM[0][2] = L.x; 134 } else { 135 GM[0][0] = (L.y - A.y) / (L.x - A.x); 136 GM[0][1] = -1; 137 GM[0][2] = (L.y - A.y) / (L.x - A.x) * A.x - A.y; 138 } 139 140 if (doubleEqual(M.x, B.x)) { 141 GM[1][0] = 1; 142 GM[1][1] = 0; 143 GM[1][2] = M.x; 144 } else { 145 GM[1][0] = (M.y - B.y) / (M.x - B.x); 146 GM[1][1] = -1; 147 GM[1][2] = (M.y - B.y) / (M.x - B.x) * B.x - B.y; 148 } 149 150 vector<double> ans = Gauss(GM, 3); 151 for (int i = 0; i < ans.size(); ++i) { 152 printf("%.4lf%c", doubleEqual(ans[i], 0) ? 0 : ans[i], i == ans.size() - 1 ? ' ' : ' '); 153 } 154 } 155 return 0; 156 }