Rendezvous on a Tetrahedron(几何、枚举,可规律)

problem

img

https://codeforces.com/gym/101986/attachments/download/7911/20172018-acmicpc-asia-tsukuba-regional-contest-en.pdf g题

思路

四面体上行走

暴力枚举6种过棱情况。。。

注意斜率是不变的

(有更简单的方法。。)

Code

#include<bits/stdc++.h>
using namespace std;
const double gen3 = 1.7320508075689;
const double eps=1e-12;
const double pi=acos(-1.0);
inline double sqr(double x){
    return x*x;
}
int cmp(double x){
    if(fabs(x) < eps) return 0;
    if(x>0) return 1;
    return -1;
}
struct point{
    double x,y;
    point(){};
    point(double _x,double _y){
        x= _x;
        y= _y;
    }
    friend point operator + (const point &a,const point &b){
        return point(a.x+b.x,a.y+b.y);
    }
    friend point operator - (const point &a,const point &b){
        return point(a.x-b.x,a.y-b.y);
    }
    friend bool operator == (const point &a,const point &b){
        return cmp(a.x-b.x) == 0 && cmp(a.y-b.y) ==0 ;
    }
    friend point operator * (const point &a,const double &b){
        return point(a.x*b,a.y*b);
    }
    friend point operator * (const double &a,const point &b){
        return point(a*b.x,a*b.y);
    }
    friend point operator / (const point &a,const double &b){
        return point(a.x/b,a.y/b);
    }
    double norm(){
        return sqrt(sqr(x)+sqr(y));
    }
};

double det(const point &a,const point &b){
    return a.x*b.y - a.y*b.x;
}

double dot(const point &a,const point &b){
    return a.x*b.x + a.y * b.y;
}

double dist(const point &a,const point &b){
    return (a-b).norm();
}

struct line{
    point a,b;
    int type;
    line(){}
    line(point aa,point bb,int t){
        a=aa;
        b=bb;
        type = t;
    }
};

bool parallel(line a,line b){
    return !cmp(det(a.a-a.b,b.a-b.b));
}
bool PointOnSegment(point p,point s,point t){
    return cmp(det(p-s,t-s))==0 && cmp(dot(p-s,p-t)) <=0 ;
}
bool line_make_point(line a,line b,point &res){
    if(parallel(a,b)) return false;
    double s1=det(a.a-b.a,b.b-b.a);
    double s2=det(a.b-b.a,b.b-b.a);
    res = (s1*a.b - s2 * a.a) / (s1-s2);
    return true;
}

point A1=point(0,gen3);
point A2=point(2,gen3);
point A3=point(1,0);
point C = point(1,gen3);
point D = point(0.5,gen3/2);
point B = point(1.5,gen3/2);

line lines[10];
point help[7];

char fix(char ans,string tp){
    if(ans!='a'){
        if(tp[0]=='B'){
            if(ans=='b') ans='d';
            else if(ans=='c') ans='b';
            else ans='c';
        }
        else if(tp[0]=='D'){
            if(ans=='b') ans='c';
            else if(ans=='c') ans='d';
            else ans='b';
        }
    }
    return ans;
}

pair<point,int> find_point(point sta,double k){
    line tmp = line(sta,point(sta.x+0.1,k*0.1+sta.y),-1);
    point res;
    int tp;
    vector<point> ans;
    for(int i=1;i<=6;++i){
        if(line_make_point(tmp,lines[i],res) && (res==sta)==false ){
            if(PointOnSegment(res,lines[i].a,lines[i].b)){
                ans.push_back(res);
                tp = i;
                break;
            }
        }
    }
    return make_pair(ans[0],tp);
}

bool in_the_tri(point A){
    if (A.y < 0.5*gen3) return false;
    if(A.x <0.5 || A.x >1.5) return false;
    if(A.x > 1) A.x = 2-A.x;
    if((A.x*gen3 >= A.y)) return true;
    return false;
}

char solve(double k,double length){
    point sta=A1;
    pair<point,int> tmp1;
    tmp1 = find_point(sta,k);
    point jiao = tmp1.first;
    int id1 = 1;
    int id2 = tmp1.second;
    double dis = dist(jiao,sta);
    while(cmp(length-dis)==1){
        length-=dis;
        double xiang = dist(jiao,help[id2]);
        assert(xiang<=1);
        xiang = (1-xiang);
        if(id2==1){
            sta = point(jiao.x+xiang,jiao.y-gen3*xiang);
        }
        else if(id2==2){
            sta = point(jiao.x+2*xiang,jiao.y);
            assert(cmp(jiao.y-gen3)==0);
        }
        else if(id2==3){
            sta = point(jiao.x-2*xiang,jiao.y);
            assert(cmp(jiao.y-gen3)==0);
        }
        else if(id2==4){
            sta = point(jiao.x-xiang,jiao.y-gen3*xiang);
        }
        else if(id2==5){
            sta = point(jiao.x+xiang,jiao.y+gen3*xiang);
        }
        else if(id2==6){
            sta = point(jiao.x-xiang,jiao.y+gen3*xiang);
        }
        id1 = id2;
        tmp1 = find_point(sta,k);
        jiao = tmp1.first;
        id2 =tmp1.second;
        dis = dist(jiao,sta);
    }
    double theta = atan(k);
    if(theta<0) theta+=pi;
    point End;
    double ahu1 =length*cos(theta);
    double ahu2 =length*sin(theta);
    if(id1==4 || id1==5) End = point(sta.x+ahu1,sta.y+ahu2);
    else End = point(sta.x-ahu1,sta.y-ahu2);
    if(in_the_tri(End)) return 'a';
    if(End.x<1 && End.y > 0.5*gen3) return 'b';
    if(End.x>1 && End.y > 0.5*gen3) return 'd';
    return 'c';
}

int main()
{
    help[1]=help[2]=A1;
    help[3]=help[4]=A2;
    help[5]=help[6]=A3;
    lines[1]=line(A1,D,1);
    lines[2]=line(A1,C,2);
    lines[3]=line(A2,C,3);
    lines[4]=line(B,A2,4);
    lines[5]=line(B,A3,5);
    lines[6]=line(D,A3,6);
    char ans1,ans2;
    string tp;
    double angle;
    double length;
    cin>>tp>>angle>>length;
    ans1 = solve(tan((180-angle)/180.0*pi),length);
    ans1 = fix(ans1,tp);
    cin>>tp>>angle>>length;
    ans2 = solve(tan((180-angle)/180.0*pi),length);
    ans2 = fix(ans2,tp);
    if(ans1==ans2) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值