1. 程式人生 > >G - Rendezvous on a Tetrahedron UVALive - 8372 計算幾何 立體轉平面

G - Rendezvous on a Tetrahedron UVALive - 8372 計算幾何 立體轉平面

題目連結: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");
    }
}