Interstellar … Fantasy 一個不很難的計算幾何
阿新 • • 發佈:2020-09-13
Interstellar … Fantasy 一個不很難的計算幾何
題意:
給你一個球,球的座標:ox,oy,oz 和球的半徑:r
再給你兩個三維座標,要求這兩個點不能穿過球,問兩點之間最短的距離是多少。
題解:
高中數學題,不是很難,注意利用角度的關係,還有餘弦定理
首先要判斷一下兩點的連線是否穿過球,如果穿過球,那麼就是兩點對球做切線,點到切點的距離加上一段圓弧的長度。
怎麼判斷是否穿過球呢,如果ost和ots都是銳角並且圓心到直線的距離小於r才可以判斷穿過球心,這兩個條件缺一不可!!!
今天的CCF出了一個差不多的題目。。。
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5+10; const double PI = acos(-1); typedef long long ll; ll dis(int x1,int y1,int z1,int x2,int y2,int z2){ return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2); } int main(){ int T; scanf("%d",&T); while(T--){ ll ox,oy,oz,r; scanf("%lld%lld%lld%lld",&ox,&oy,&oz,&r); ll sx,sy,sz,tx,ty,tz; scanf("%lld%lld%lld%lld%lld%lld",&sx,&sy,&sz,&tx,&ty,&tz); double SO = sqrt(1.0*dis(sx,sy,sz,ox,oy,oz)); double TO = sqrt(1.0*dis(tx,ty,tz,ox,oy,oz)); double ST = sqrt(1.0*dis(sx,sy,sz,tx,ty,tz)); double deltS = acos(1.0*r/SO); double deltT = acos(1.0*r/TO); double delt = acos((SO*SO+TO*TO-ST*ST)/(2*SO*TO))-deltT-deltS; double Tx = acos((ST*ST+TO*TO-SO*SO)/(2*ST*TO)); double Sx = acos((ST*ST+SO*SO-TO*TO)/(2*ST*SO)); double h = TO*sin(Tx),ans = 0; if(Sx<PI/2&&Tx<PI/2&&h<r) ans = sqrt(SO*SO-r*r)+sqrt(TO*TO-r*r)+delt*r; else ans = ST; // cout<<ans<<endl; printf("%.8f\n",ans); } }