【HDU5733 2016 Multi-University Training Contest 1K】【计算几何 公式做法】tetrahedron 四面体内切球圆心与半径
2016-07-25 10:02
621 查看
tetrahedron
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 723 Accepted Submission(s): 294
[align=left]Problem Description[/align]
Given four points ABCD, if ABCD is a tetrahedron, calculate the inscribed sphere of ABCD.
[align=left]Input[/align]
Multiple test cases (test cases ≤100).
Each test cases contains a line of 12 integers [−1e6,1e6] indicate
the coordinates of four vertices of ABCD.
Input ends by EOF.
[align=left]Output[/align]
Print the coordinate of the center of the sphere and the radius, rounded to 4 decimal places.
If there is no such sphere, output "O O O O".
[align=left]Sample Input[/align]
0 0 0 2 0 0 0 0 2 0 2 0
0 0 0 2 0 0 3 0 0 4 0 0
[align=left]Sample Output[/align]
0.4226 0.4226 0.4226 0.4226
O O O O
[align=left]Author[/align]
HIT
[align=left]Source[/align]
2016 Multi-University Training
Contest 1
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; } template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; } const int N = 0, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f; int casenum, casei; const double eps = 1e-6; //既可以定义为点,又可以定为为向量 struct Point { LL x, y, z; Point(LL x = 0, LL y = 0, LL z = 0) :x(x), y(y), z(z) {}; bool input() { return ~scanf("%lld%lld%lld", &x, &y, &z); } Point operator - (Point &b)const { return Point(x - b.x, y - b.y, z - b.z); } Point operator * (Point &b)const { return Point(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); } double length() { return sqrt(x*x + y*y + z*z); } }p[4]; //已知四面体的6条棱长,求出四面体体积 double volume(double l, double n, double a, double m, double b, double c) { double x, y; x = 4 * a * a * b * b * c * c - a * a * (b * b + c * c - m * m) * (b * b + c * c - m * m) - b * b * (c * c + a * a - n * n) * (c * c + a * a - n * n); y = c * c * (a * a + b * b - l * l) * (a * a + b * b - l * l) - (a * a + b * b - l * l) * (b * b + c * c - m * m) * (c * c + a * a - n * n); return sqrt(x - y) / 12; } //已知三角形边长,求出三边形面积 double S(double a, double b, double c) { double p = (a + b + c) / 2; return sqrt(p * (p - a) * (p - b) * (p - c)); } double d[4][4]; //求两点之间的距离 double s[4]; //求该点所对平面的面积 int main() { while (p[0].input(), p[1].input(), p[2].input(), p[3].input()) { for (int i = 0; i < 4; ++i) { for (int j = i + 1; j < 4; ++j)d[i][j] = d[j][i] = (p[j] - p[i]).length(); } double vol = volume(d[0][1], d[0][2], d[0][3], d[1][2], d[1][3], d[2][3]); double area = 0; for (int i = 0; i < 4; ++i) { vector<double>vt; for (int j = 0; j < 4; ++j)if (j != i) { for (int k = j + 1; k < 4; ++k)if (k != i)vt.push_back(d[j][k]); } s[i] = S(vt[0], vt[1], vt[2]); area += s[i]; } if (fabs(vol) < eps || fabs(area) < eps)puts("O O O O"); else { double x = 0; for (int i = 0; i < 4; ++i)x += s[i] * p[i].x; x /= area; double y = 0; for (int i = 0; i < 4; ++i)y += s[i] * p[i].y; y /= area; double z = 0; for (int i = 0; i < 4; ++i)z += s[i] * p[i].z; z /= area; double r = vol * 3 / area; printf("%.4f %.4f %.4f %.4f\n", x, y, z, r); } } return 0; } /* 【题意】 给你四个点。 让你求四个点是否共面,不共面的话,求出其内切球的球心以及半径。 【类型】 计算几何 【分析】 这题我直接二话不说, 写了一个三分套三分套三分。 但是常数巨大于是TLE了。 还是推公式靠谱。 首先,我们求出该四面体的6条棱长和4个面积之后, 6条棱长可以直接求出四面体体积。 然后(体积*3)/面积之和,就是其内切球的半径。 内切球的圆心公式,有一种非常美的表现形式—— double x = 0; for (int i = 0; i < 4; ++i)x += s[i] * p[i].x; x /= area; double y = 0; for (int i = 0; i < 4; ++i)y += s[i] * p[i].y; y /= area; double z = 0; for (int i = 0; i < 4; ++i)z += s[i] * p[i].z; z /= area; double r = vol * 3 / area; printf("%.4f %.4f %.4f %.4f\n", x, y, z, r); 即4个点(三维坐标*对面面积)关于总面积的加权平均值。 其实,这个可以是由三角形的内切圆推广而来 内切圆的圆心, 是3个点(三维坐标*对边边长)关于总边长的加权平均值。 【时间复杂度&&优化】 O(1) 【数据】 */
相关文章推荐
- 初学算法 - 求凸包的Garham's Scan算法的C++实现
- 【Google Code Jam 2009 round2 problem D】Watering Plants (两圆交点求法详解)
- 计算几何模板
- 计算几何小模板
- BZOJ2829信用卡凸包
- HDU 4922 Hello, Your Package! (计算几何+DP)(WA)
- poj 1514&zoj 1185 Metal Cutting(半平面交)
- UVA 10969 Sweet Dream(圆的相交)
- uva 11177 Fighting Against a Polygonal Monster(凸包与圆的面积交)
- POJ1279 && LA2512 Art Gallery(求多边形的核)
- poj 2540 && uva 10084 Hotter Colder(半平面交)
- UVALive 5878 - Shortest Leash 【计算几何】
- 【计算几何】POJ 2318 & POJ 2398
- 【计算几何】POJ 2653
- 【计算几何】POJ 1113
- HDU 5128 The E-pang Palace
- POJ 2318 TOYS(叉积+二分or暴力)
- POJ 2398 Toy Storage(叉积+二分)
- POJ 1228 Grandpa's Estate 计算凸包+判断点在线段上
- POJ 1873 The Fortified Forest 计算凸包