1. 程式人生 > >[THOJ 1589] 橢球面 三分套三分

[THOJ 1589] 橢球面 三分套三分

ring nan urn span bsp sqrt 計算 gis cstring

題意

  現在給出一個橢球面: $ax ^ 2 + by ^ 2 + cz ^ 2 + dyz + exz + fxy = 1$ .

  求橢球面到 $(0, 0, 0)$ 的距離.

  $T \le 200, 0 < a, b, c < 1, 0 \le d, e, f < 1$ .

  假裝 $(0, 0, 0)$ 在橢球內部.

分析

  二次的式子通常都是單峰的.

  猜測橢球到 $(0, 0, 0)$ 的距離也是單峰的.

  三分 x , 三分 y , 利用一元二次方程解出 z 並計算距離.

實現

  實現小結:

    1. 對於三分, 模擬退火之類的, 最好記錄訪問到的最大的答案, 而不是最後再求一次.

    2. 浮點數上, 如果運算出錯, 會返回 nan , 判斷一個數是不是 nan , 就判斷 !(x < 0) && !(x >= 0) .

  最終實現:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
 9
#define db double 10 11 const db INF = 1e30; 12 13 db a, b, c, d, e, f, ans; 14 15 inline bool nan(db x) { return !(x < 0) && !(x >= 0); } 16 inline db Dist(db x, db y, db z) { return sqrt(x * x + y * y + z * z); } 17 inline db Calc(db x, db y) { 18 db A = c; 19 db B = d * y + e * x;
20 db C = a * x * x + b * y * y + f * x * y - 1; 21 db D = B * B - 4 * A * C; 22 db z = (-B - sqrt(D)) / (2 * A); 23 db tmp = Dist(x, y, z); 24 return ans = min(ans, tmp), tmp; 25 } 26 inline db Y(db x) { 27 db l = 0, r = 1000 / sqrt(b); 28 while (r-l > 1e-10) { 29 db _l = (l+l+r)/3, ansL = Calc(x, _l); 30 db _r = (l+r+r)/3, ansR = Calc(x, _r); 31 nan(ansL) || nan(ansR) || ansL < ansR ? r = _r : l = _l; 32 } 33 db ans = Calc(x, l); 34 35 l = -1000 / sqrt(b), r = 0; 36 while (r-l > 1e-10) { 37 db _l = (l+l+r)/3, ansL = Calc(x, _l); 38 db _r = (l+r+r)/3, ansR = Calc(x, _r); 39 nan(ansL) || nan(ansR) || ansR < ansL ? l = _l : r = _r; 40 } 41 db ans2 = Calc(x, l); 42 43 return nan(ans) ? ans2 : nan(ans2) ? ans : min(ans, ans2); 44 } 45 inline db X(void) { 46 db l = 0, r = 1000 / sqrt(a); 47 while (r-l > 1e-10) { 48 db _l = (l+l+r)/3, ansL = Y(_l); 49 db _r = (l+r+r)/3, ansR = Y(_r); 50 nan(ansL) || nan(ansR) || ansL < ansR ? r = _r : l = _l; 51 } 52 db ans = Y(l); 53 54 l = -1000 / sqrt(a), r = 0; 55 while (r-l > 1e-10) { 56 db _l = (l+l+r)/3, ansL = Y(_l); 57 db _r = (l+r+r)/3, ansR = Y(_r); 58 nan(ansL) || nan(ansR) || ansR < ansL ? l = _l : r = _r; 59 } 60 db ans2 = Y(l); 61 62 return nan(ans) ? ans2 : nan(ans2) ? ans : min(ans, ans2); 63 } 64 65 int main(void) { 66 #ifndef ONLINE_JUDGE 67 freopen("e.in", "r", stdin); 68 #endif 69 70 while (~scanf("%lf %lf %lf %lf %lf %lf", &a, &b, &c, &d, &e, &f)) 71 ans = INF, X(), printf("%0.8lf\n", ans); 72 73 return 0; 74 }

[THOJ 1589] 橢球面 三分套三分