POJ 2208 Pyramids(求四面体体积)
Description
Recently in Farland, a country in Asia, a famous scientist Mr. Log Archeo has discovered ancient pyramids. But unlike those in Egypt and Central America, they have triangular (not rectangular) foundation. That is, they are tetrahedrons in mathematical sense. In order to find out some important facts about the early society of the country (it is widely believed that the pyramid sizes are in tight connection with Farland ancient calendar), Mr. Archeo needs to know the volume of the pyramids. Unluckily, he has reliable data about their edge lengths only. Please, help him!
Input
The file contains six positive integer numbers not exceeding 1000 separated by spaces, each number is one of the edge lengths of the pyramid ABCD. The order of the edges is the following: AB, AC, AD, BC, BD, CD.
Output
A real number -- the volume printed accurate to four digits after decimal point.
题目大意:给四面体的六条边,求这个四面体的体积。
思路:用欧拉四面体公式,注意每条边的对应关系。
代码(47MS):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 #define sqr(x) ((x) * (x)) 8 9 typedef long long LL; 10 typedef long double LD; 11 12 const int MAXN = 55; 13 const double EPS = 1e-10; 14 const double PI = acos(-1.0);//3.14159265358979323846 15 const double INF = 1; 16 17 inline int sgn(double x) { 18 return (x > EPS) - (x < -EPS); 19 } 20 21 struct Point { 22 double x, y, ag; 23 Point() {} 24 Point(double x, double y): x(x), y(y) {} 25 void read() { 26 scanf("%lf%lf", &x, &y); 27 } 28 bool operator == (const Point &rhs) const { 29 return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0; 30 } 31 bool operator < (const Point &rhs) const { 32 if(y != rhs.y) return y < rhs.y; 33 return x < rhs.x; 34 } 35 Point operator + (const Point &rhs) const { 36 return Point(x + rhs.x, y + rhs.y); 37 } 38 Point operator - (const Point &rhs) const { 39 return Point(x - rhs.x, y - rhs.y); 40 } 41 Point operator * (const double &b) const { 42 return Point(x * b, y * b); 43 } 44 Point operator / (const double &b) const { 45 return Point(x / b, y / b); 46 } 47 double operator * (const Point &rhs) const { 48 return x * rhs.x + y * rhs.y; 49 } 50 double length() { 51 return sqrt(x * x + y * y); 52 } 53 double angle() { 54 return atan2(y, x); 55 } 56 Point unit() { 57 return *this / length(); 58 } 59 void makeAg() { 60 ag = atan2(y, x); 61 } 62 void print() { 63 printf("%.10f %.10f\n", x, y); 64 } 65 }; 66 typedef Point Vector; 67 68 double dist(const Point &a, const Point &b) { 69 return (a - b).length(); 70 } 71 72 double cross(const Point &a, const Point &b) { 73 return a.x * b.y - a.y * b.x; 74 } 75 //ret >= 0 means turn right 76 double cross(const Point &sp, const Point &ed, const Point &op) { 77 return cross(sp - op, ed - op); 78 } 79 80 double area(const Point& a, const Point &b, const Point &c) { 81 return fabs(cross(a - c, b - c)) / 2; 82 } 83 //counter-clockwise 84 Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) { 85 Point t = p - o; 86 double x = t.x * cos(angle) - t.y * sin(angle); 87 double y = t.y * cos(angle) + t.x * sin(angle); 88 return Point(x, y) + o; 89 } 90 91 double cosIncludeAngle(const Point &a, const Point &b, const Point &o) { 92 Point p1 = a - o, p2 = b - o; 93 return (p1 * p2) / (p1.length() * p2.length()); 94 } 95 96 double includedAngle(const Point &a, const Point &b, const Point &o) { 97 return acos(cosIncludeAngle(a, b, o)); 98 /* 99 double ret = abs((a - o).angle() - (b - o).angle()); 100 if(sgn(ret - PI) > 0) ret = 2 * PI - ret; 101 return ret; 102 */ 103 } 104 105 struct Seg { 106 Point st, ed; 107 double ag; 108 Seg() {} 109 Seg(Point st, Point ed): st(st), ed(ed) {} 110 void read() { 111 st.read(); ed.read(); 112 } 113 void makeAg() { 114 ag = atan2(ed.y - st.y, ed.x - st.x); 115 } 116 }; 117 typedef Seg Line; 118 119 //ax + by + c > 0 120 Line buildLine(double a, double b, double c) { 121 if(sgn(a) == 0 && sgn(b) == 0) return Line(Point(sgn(c) > 0 ? -1 : 1, INF), Point(0, INF)); 122 if(sgn(a) == 0) return Line(Point(sgn(b), -c/b), Point(0, -c/b)); 123 if(sgn(b) == 0) return Line(Point(-c/a, 0), Point(-c/a, sgn(a))); 124 if(b < 0) return Line(Point(0, -c/b), Point(1, -(a + c) / b)); 125 else return Line(Point(1, -(a + c) / b), Point(0, -c/b)); 126 } 127 128 void moveRight(Line &v, double r) { 129 double dx = v.ed.x - v.st.x, dy = v.ed.y - v.st.y; 130 dx = dx / dist(v.st, v.ed) * r; 131 dy = dy / dist(v.st, v.ed) * r; 132 v.st.x += dy; v.ed.x += dy; 133 v.st.y -= dx; v.ed.y -= dx; 134 } 135 136 bool isOnSeg(const Seg &s, const Point &p) { 137 return (p == s.st || p == s.ed) || 138 (((p.x - s.st.x) * (p.x - s.ed.x) < 0 || 139 (p.y - s.st.y) * (p.y - s.ed.y) < 0) && 140 sgn(cross(s.ed, p, s.st)) == 0); 141 } 142 143 bool isInSegRec(const Seg &s, const Point &p) { 144 return sgn(min(s.st.x, s.ed.x) - p.x) <= 0 && sgn(p.x - max(s.st.x, s.ed.x)) <= 0 145 && sgn(min(s.st.y, s.ed.y) - p.y) <= 0 && sgn(p.y - max(s.st.y, s.ed.y)) <= 0; 146 } 147 148 bool isIntersected(const Point &s1, const Point &e1, const Point &s2, const Point &e2) { 149 return (max(s1.x, e1.x) >= min(s2.x, e2.x)) && 150 (max(s2.x, e2.x) >= min(s1.x, e1.x)) && 151 (max(s1.y, e1.y) >= min(s2.y, e2.y)) && 152 (max(s2.y, e2.y) >= min(s1.y, e1.y)) && 153 (cross(s2, e1, s1) * cross(e1, e2, s1) >= 0) && 154 (cross(s1, e2, s2) * cross(e2, e1, s2) >= 0); 155 } 156 157 bool isIntersected(const Seg &a, const Seg &b) { 158 return isIntersected(a.st, a.ed, b.st, b.ed); 159 } 160 161 bool isParallel(const Seg &a, const Seg &b) { 162 return sgn(cross(a.ed - a.st, b.ed - b.st)) == 0; 163 } 164 165 //return Ax + By + C =0 's A, B, C 166 void Coefficient(const Line &L, double &A, double &B, double &C) { 167 A = L.ed.y - L.st.y; 168 B = L.st.x - L.ed.x; 169 C = L.ed.x * L.st.y - L.st.x * L.ed.y; 170 } 171 //point of intersection 172 Point operator * (const Line &a, const Line &b) { 173 double A1, B1, C1; 174 double A2, B2, C2; 175 Coefficient(a, A1, B1, C1); 176 Coefficient(b, A2, B2, C2); 177 Point I; 178 I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1); 179 I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1); 180 return I; 181 } 182 183 bool isEqual(const Line &a, const Line &b) { 184 double A1, B1, C1; 185 double A2, B2, C2; 186 Coefficient(a, A1, B1, C1); 187 Coefficient(b, A2, B2, C2); 188 return sgn(A1 * B2 - A2 * B1) == 0 && sgn(A1 * C2 - A2 * C1) == 0 && sgn(B1 * C2 - B2 * C1) == 0; 189 } 190 191 double Point_to_Line(const Point &p, const Line &L) { 192 return fabs(cross(p, L.st, L.ed)/dist(L.st, L.ed)); 193 } 194 195 double Point_to_Seg(const Point &p, const Seg &L) { 196 if(sgn((L.ed - L.st) * (p - L.st)) < 0) return dist(p, L.st); 197 if(sgn((L.st - L.ed) * (p - L.ed)) < 0) return dist(p, L.ed); 198 return Point_to_Line(p, L); 199 } 200 201 double Seg_to_Seg(const Seg &a, const Seg &b) { 202 double ans1 = min(Point_to_Seg(a.st, b), Point_to_Seg(a.ed, b)); 203 double ans2 = min(Point_to_Seg(b.st, a), Point_to_Seg(b.ed, a)); 204 return min(ans1, ans2); 205 } 206 207 struct Circle { 208 Point c; 209 double r; 210 Circle() {} 211 Circle(Point c, double r): c(c), r(r) {} 212 void read() { 213 c.read(); 214 scanf("%lf", &r); 215 } 216 double area() const { 217 return PI * r * r; 218 } 219 bool contain(const Circle &rhs) const { 220 return sgn(dist(c, rhs.c) + rhs.r - r) <= 0; 221 } 222 bool contain(const Point &p) const { 223 return sgn(dist(c, p) - r) <= 0; 224 } 225 bool intersect(const Circle &rhs) const { 226 return sgn(dist(c, rhs.c) - r - rhs.r) < 0; 227 } 228 bool tangency(const Circle &rhs) const { 229 return sgn(dist(c, rhs.c) - r - rhs.r) == 0; 230 } 231 Point pos(double angle) const { 232 Point p = Point(c.x + r, c.y); 233 return rotate(p, angle, c); 234 } 235 }; 236 237 double CommonArea(const Circle &A, const Circle &B) { 238 double area = 0.0; 239 const Circle & M = (A.r > B.r) ? A : B; 240 const Circle & N = (A.r > B.r) ? B : A; 241 double D = dist(M.c, N.c); 242 if((D < M.r + N.r) && (D > M.r - N.r)) { 243 double cosM = (M.r * M.r + D * D - N.r * N.r) / (2.0 * M.r * D); 244 double cosN = (N.r * N.r + D * D - M.r * M.r) / (2.0 * N.r * D); 245 double alpha = 2 * acos(cosM); 246 double beta = 2 * acos(cosN); 247 double TM = 0.5 * M.r * M.r * (alpha - sin(alpha)); 248 double TN = 0.5 * N.r * N.r * (beta - sin(beta)); 249 area = TM + TN; 250 } 251 else if(D <= M.r - N.r) { 252 area = N.area(); 253 } 254 return area; 255 } 256 257 int intersection(const Seg &s, const Circle &cir, Point &p1, Point &p2) { 258 double angle = cosIncludeAngle(s.ed, cir.c, s.st); 259 //double angle1 = cos(includedAngle(s.ed, cir.c, s.st)); 260 double B = dist(cir.c, s.st); 261 double a = 1, b = -2 * B * angle, c = sqr(B) - sqr(cir.r); 262 double delta = sqr(b) - 4 * a * c; 263 if(sgn(delta) < 0) return 0; 264 if(sgn(delta) == 0) delta = 0; 265 double x1 = (-b - sqrt(delta)) / (2 * a), x2 = (-b + sqrt(delta)) / (2 * a); 266 Vector v = (s.ed - s.st).unit(); 267 p1 = s.st + v * x1; 268 p2 = s.st + v * x2; 269 return 1 + sgn(delta); 270 } 271 272 double CommonArea(const Circle &cir, Point p1, Point p2) { 273 if(p1 == cir.c || p2 == cir.c) return 0; 274 if(cir.contain(p1) && cir.contain(p2)) { 275 return area(cir.c, p1, p2); 276 } else if(!cir.contain(p1) && !cir.contain(p2)) { 277 Point q1, q2; 278 int t = intersection(Line(p1, p2), cir, q1, q2); 279 if(t == 0) { 280 double angle = includedAngle(p1, p2, cir.c); 281 return 0.5 * sqr(cir.r) * angle; 282 } else { 283 double angle1 = includedAngle(p1, p2, cir.c); 284 double angle2 = includedAngle(q1, q2, cir.c); 285 if(isInSegRec(Seg(p1, p2), q1))return 0.5 * sqr(cir.r) * (angle1 - angle2 + sin(angle2)); 286 else return 0.5 * sqr(cir.r) * angle1; 287 } 288 } else { 289 if(cir.contain(p2)) swap(p1, p2); 290 Point q1, q2; 291 intersection(Line(p1, p2), cir, q1, q2); 292 double angle = includedAngle(q2, p2, cir.c); 293 double a = area(cir.c, p1, q2); 294 double b = 0.5 * sqr(cir.r) * angle; 295 return a + b; 296 } 297 } 298 299 struct Triangle { 300 Point p[3]; 301 Triangle() {} 302 Triangle(Point *t) { 303 for(int i = 0; i < 3; ++i) p[i] = t[i]; 304 } 305 void read() { 306 for(int i = 0; i < 3; ++i) p[i].read(); 307 } 308 double area() const { 309 return ::area(p[0], p[1], p[2]); 310 } 311 Point& operator[] (int i) { 312 return p[i]; 313 } 314 }; 315 316 double CommonArea(Triangle tir, const Circle &cir) { 317 double ret = 0; 318 ret += sgn(cross(tir[0], cir.c, tir[1])) * CommonArea(cir, tir[0], tir[1]); 319 ret += sgn(cross(tir[1], cir.c, tir[2])) * CommonArea(cir, tir[1], tir[2]); 320 ret += sgn(cross(tir[2], cir.c, tir[0])) * CommonArea(cir, tir[2], tir[0]); 321 return abs(ret); 322 } 323 324 struct Poly { 325 int n; 326 Point p[MAXN];//p[n] = p[0] 327 void init(Point *pp, int nn) { 328 n = nn; 329 for(int i = 0; i < n; ++i) p[i] = pp[i]; 330 p[n] = p[0]; 331 } 332 double area() { 333 if(n < 3) return 0; 334 double s = p[0].y * (p[n - 1].x - p[1].x); 335 for(int i = 1; i < n; ++i) 336 s += p[i].y * (p[i - 1].x - p[i + 1].x); 337 return s / 2; 338 } 339 }; 340 //the convex hull is clockwise 341 void Graham_scan(Point *p, int n, int *stk, int &top) {//stk[0] = stk[top] 342 sort(p, p + n); 343 top = 1; 344 stk[0] = 0; stk[1] = 1; 345 for(int i = 2; i < n; ++i) { 346 while(top && cross(p[i], p[stk[top]], p[stk[top - 1]]) <= 0) --top; 347 stk[++top] = i; 348 } 349 int len = top; 350 stk[++top] = n - 2; 351 for(int i = n - 3; i >= 0; --i) { 352 while(top != len && cross(p[i], p[stk[top]], p[stk[top - 1]]) <= 0) --top; 353 stk[++top] = i; 354 } 355 } 356 //use for half_planes_cross 357 bool cmpAg(const Line &a, const Line &b) { 358 if(sgn(a.ag - b.ag) == 0) 359 return sgn(cross(b.ed, a.st, b.st)) < 0; 360 return a.ag < b.ag; 361 } 362 //clockwise, plane is on the right 363 bool half_planes_cross(Line *v, int vn, Poly &res, Line *deq) { 364 int i, n; 365 sort(v, v + vn, cmpAg); 366 for(i = n = 1; i < vn; ++i) { 367 if(sgn(v[i].ag - v[i-1].ag) == 0) continue; 368 v[n++] = v[i]; 369 } 370 int head = 0, tail = 1; 371 deq[0] = v[0], deq[1] = v[1]; 372 for(i = 2; i < n; ++i) { 373 if(isParallel(deq[tail - 1], deq[tail]) || isParallel(deq[head], deq[head + 1])) 374 return false; 375 while(head < tail && sgn(cross(v[i].ed, deq[tail - 1] * deq[tail], v[i].st)) > 0) 376 --tail; 377 while(head < tail && sgn(cross(v[i].ed, deq[head] * deq[head + 1], v[i].st)) > 0) 378 ++head; 379 deq[++tail] = v[i]; 380 } 381 while(head < tail && sgn(cross(deq[head].ed, deq[tail - 1] * deq[tail], deq[head].st)) > 0) 382 --tail; 383 while(head < tail && sgn(cross(deq[tail].ed, deq[head] * deq[head + 1], deq[tail].st)) > 0) 384 ++head; 385 if(tail <= head + 1) return false; 386 res.n = 0; 387 for(i = head; i < tail; ++i) 388 res.p[res.n++] = deq[i] * deq[i + 1]; 389 res.p[res.n++] = deq[head] * deq[tail]; 390 res.n = unique(res.p, res.p + res.n) - res.p; 391 res.p[res.n] = res.p[0]; 392 return true; 393 } 394 395 //ix and jx is the points whose distance is return, res.p[n - 1] = res.p[0], res must be clockwise 396 double dia_rotating_calipers(Poly &res, int &ix, int &jx) { 397 double dia = 0; 398 int q = 1; 399 for(int i = 0; i < res.n - 1; ++i) { 400 while(sgn(cross(res.p[i], res.p[q + 1], res.p[i + 1]) - cross(res.p[i], res.p[q], res.p[i + 1])) > 0) 401 q = (q + 1) % (res.n - 1); 402 if(sgn(dist(res.p[i], res.p[q]) - dia) > 0) { 403 dia = dist(res.p[i], res.p[q]); 404 ix = i; jx = q; 405 } 406 if(sgn(dist(res.p[i + 1], res.p[q]) - dia) > 0) { 407 dia = dist(res.p[i + 1], res.p[q]); 408 ix = i + 1; jx = q; 409 } 410 } 411 return dia; 412 } 413 //a and b must be clockwise, find the minimum distance between two convex hull 414 double half_rotating_calipers(Poly &a, Poly &b) { 415 int sa = 0, sb = 0; 416 for(int i = 0; i < a.n; ++i) if(sgn(a.p[i].y - a.p[sa].y) < 0) sa = i; 417 for(int i = 0; i < b.n; ++i) if(sgn(b.p[i].y - b.p[sb].y) < 0) sb = i; 418 double tmp, ans = dist(a.p[0], b.p[0]); 419 for(int i = 0; i < a.n; ++i) { 420 while(sgn(tmp = cross(a.p[sa], a.p[sa + 1], b.p[sb + 1]) - cross(a.p[sa], a.p[sa + 1], b.p[sb])) > 0) 421 sb = (sb + 1) % (b.n - 1); 422 if(sgn(tmp) < 0) ans = min(ans, Point_to_Seg(b.p[sb], Seg(a.p[sa], a.p[sa + 1]))); 423 else ans = min(ans, Seg_to_Seg(Seg(a.p[sa], a.p[sa + 1]), Seg(b.p[sb], b.p[sb + 1]))); 424 sa = (sa + 1) % (a.n - 1); 425 } 426 return ans; 427 } 428 429 double rotating_calipers(Poly &a, Poly &b) { 430 return min(half_rotating_calipers(a, b), half_rotating_calipers(b, a)); 431 } 432 //欧拉四面体公式AB, AC, AD, BC, BD, CD 433 double area(double p, double q, double r, double n, double m, double l) { 434 p *= p, q *= q, r *= r, n *= n, m *= m, l *= l; 435 long double ret = 0; 436 ret += LD(p) * q * r; 437 ret += LD(p + q - n) * (q + r - l) * (p + r - m) / 4; 438 ret -= LD(p + r - m) * q * (p + r - m) / 4; 439 ret -= LD(p + q - n) * (p + q - n) * r / 4; 440 ret -= LD(q + r - l) * (q + r - l) * p / 4; 441 return sqrt(ret / 36); 442 } 443 444 /*******************************************************************************************/ 445 446 Point p[MAXN]; 447 Circle cir; 448 double r; 449 int n; 450 451 int main() { 452 double p, q, r, n, m, l; 453 while(cin>>p>>q>>r>>n>>m>>l) { 454 printf("%.4f\n", area(p, q, r, n, m, l)); 455 } 456 }