G - Rendezvous on a Tetrahedron UVALive - 8372 計算幾何 立體轉平面
阿新 • • 發佈:2018-12-11
題目連結:https://vj.e949.cn/f376bdaed6c2100cb7a5b94c3cb00e3d?v=1542418343
題意:
給你一個單位長度的四面體,兩隻蝸牛同時從頂點A開始爬,告訴你它會向哪邊爬以及與哪條邊的夾角為多少,告訴你爬行的長度,問你最後這兩隻蝸牛是否再同一個平面上。
做法:
和隊友的討論出真知啊!感慨一下。
題目將立體問題轉化為平面問題,因為往一個方向走之後,只要只要遇到哪條邊那麼下一個三角形也就能知道,所以其實可以直接將這些畫成一個平面的圖,以下是我心靈手巧的隊長畫的圖。很容易發現,上下移動2根號3或者左右移動2之後得到的值是在同一個區域內的,即繞了一個圈,那麼我們只要預處理出所有在橫座標0~2,縱座標0~2根號3種的所有區域塊,同時求得蝸牛最後平移後的落點,利用叉積進行運算即可。
#include<bits/stdc++.h> using namespace std; const double eps=1e-8; struct Point{ double x,y; Point(){} Point(double x,double y):x(x),y(y){} }; struct node{ Point p1,p2,p3; int blo; node(Point p1,Point p2,Point p3,int blo):p1(p1),p2(p2),p3(p3),blo(blo){} }; int dcmp(double a){ if(fabs(a)<eps) return 0; if(a>0) return 1; return -1; } vector<node> ve; void init(){ double r=sqrt(3)/2;double r2=2.0*r,r3=3.0*r,r4=4.0*r; ve.push_back(node(Point(0,0),Point(1,0),Point(0.5,r),1)); ve.push_back(node(Point(0,r2),Point(1,r2),Point(0.5,r),1)); ve.push_back(node(Point(1,r2),Point(2,r2),Point(1.5,r3),1)); ve.push_back(node(Point(1,r4),Point(2,r4),Point(1.5,r3),1)); ve.push_back(node(Point(1,0),Point(2,0),Point(1.5,r),4)); ve.push_back(node(Point(1,r2),Point(2,r2),Point(1.5,r),4)); ve.push_back(node(Point(0,r2),Point(1,r2),Point(0.5,r3),4)); ve.push_back(node(Point(0,r4),Point(1,r4),Point(0.5,r3),4)); ve.push_back(node(Point(0,r2),Point(-0.5,r),Point(0.5,r),2)); ve.push_back(node(Point(-0.5,r3),Point(0,r2),Point(0.5,r3),2)); ve.push_back(node(Point(0.5,r),Point(1,0),Point(1.5,r),2)); ve.push_back(node(Point(1.5,r),Point(2.5,r),Point(2,r2),2)); ve.push_back(node(Point(1.5,r3),Point(2.5,r3),Point(2,r2),2)); ve.push_back(node(Point(0.5,r3),Point(1.5,r3),Point(1,r4),2)); ve.push_back(node(Point(0,0),Point(-0.5,r),Point(0.5,r),3)); ve.push_back(node(Point(-0.5,r3),Point(0,r4),Point(0.5,r3),3)); ve.push_back(node(Point(0.5,r),Point(1,r2),Point(1.5,r),3)); ve.push_back(node(Point(1.5,r),Point(2.5,r),Point(2,0),3)); ve.push_back(node(Point(1.5,r3),Point(2.5,r3),Point(2,r4),3)); ve.push_back(node(Point(0.5,r3),Point(1.5,r3),Point(1,r2),3)); } Point operator - (Point a, Point b){ return Point(a.x - b.x, a.y - b.y); } double cha(Point a,Point b){ /*cout<<a.x<<" "<<a.y<<endl; cout<<b.x<<" "<<b.y<<endl; cout<<a.x*b.y-a.y*b.x<<endl;*/ return a.x*b.y-a.y*b.x; } int ck(Point a,node b){ //cout<<cha(a-b.p1,a-b.p2)*cha(b.p3-b.p1,b.p3-b.p2)<<" "<<cha(a-b.p2,a-b.p3)*cha(b.p1-b.p2,b.p1-b.p3)<<" "<<cha(a-b.p3,a-b.p1)*cha(b.p2-b.p3,b.p2-b.p1)<<endl; if(dcmp(cha(a-b.p1,a-b.p2)*cha(b.p3-b.p1,b.p3-b.p2))>0&&dcmp(cha(a-b.p2,a-b.p3)*cha(b.p1-b.p2,b.p1-b.p3))>0&&dcmp(cha(a-b.p3,a-b.p1)*cha(b.p2-b.p3,b.p2-b.p1))>0) return 1; return 0; } int judge(Point x){ for(int i=0;i<ve.size();i++){ //cout<<i<<endl; if(ck(x,ve[i])) { return ve[i].blo; } } } char s1[5],s2[5]; double an1,len1,an2,len2; int main(){ init(); while(~scanf("%s%lf%lf%s%lf%lf",s1,&an1,&len1,s2,&an2,&len2)){ double ang; if(s1[0]=='B') ang=an1; else if(s1[0]=='C') ang=60.0+an1; else if(s1[0]=='D') ang=120.0+an1; ang=ang/180.0*acos(-1); double x,y,rr=2.0*sqrt(3); x=len1*cos(ang),y=len1*sin(ang); while(x<-eps) x+=2.0; while(x-2.0>eps) x-=2.0; while(y<-eps) y+=rr; while(y-rr>eps) y-=rr; Point fi(x,y); int blo1=judge(fi); if(s2[0]=='B') ang=an2; else if(s2[0]=='C') ang=60.0+an2; else if(s2[0]=='D') ang=120.0+an2; ang=ang/180.0*acos(-1); x=len2*cos(ang),y=len2*sin(ang); while(x<-eps) x+=2.0; while(x-2.0>eps) x-=2.0; while(y<-eps) y+=rr; while(y-rr>eps) y-=rr; Point se(x,y); int blo2=judge(se); //printf("blo1=%d blo2=%d\n",blo1,blo2); if(blo1==blo2) printf("YES\n"); else printf("NO\n"); } }