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):
  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 }
View Code

 

posted @ 2013-11-23 15:18  Oyking  阅读(308)  评论(0编辑  收藏  举报