题目链接: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");
}
}