[Codeforces 32E] Hide-and-Seek

Brief Intro:

给两个人的坐标,一堵墙和一面镜子,询问两人能否看见对方

Solution:

一道以分类讨论为主的计算几何题,

分别讨论两人坐标连线是否经过墙/镜子即可,

难点在于如何求出点x关于线段[A,B]的对称点:

point sym(point x,point A,point B){return 2*dot(A,B)/dot(B,B)*B-A+x;}

以上给出一种方法:将线段[x,A]延长一倍,求出线段[x,x']的向量,再行加减即可

Code:

扫描二维码关注公众号,回复: 1044901 查看本文章
#include <bits/stdc++.h>

using namespace std;

typedef complex<double> point;

point a,b,w1,w2,m1,m2;

point read(){double x,y;cin>>x>>y;return point(x,y);}
double det(point a,point b){return imag(a*conj(b));}
double dot(point a,point b){return real(a*conj(b));}
bool on_seg(point x,point L,point R){return det(L-x,R-x)==0 && dot(L-x,R-x)<=0;}
bool seg_cross(point a,point b,point c,point d)
{
    double s1=det(c-a,b-a)*det(b-a,d-a);
    double s2=det(a-c,d-c)*det(d-c,b-c);
    if(s1<0 || s2<0) return false;
    if(s1==0 && s2==0) return on_seg(c,a,b) || on_seg(d,a,b);
    return true; 
}
point sym(point x,point A,point B){return 2*dot(A,B)/dot(B,B)*B-A+x;}

bool check()
{
    if(seg_cross(a,b,m1,m2))
        return !seg_cross(a,b,w1,w2) && det(b-a,m2-m1)==0;
    else if(seg_cross(a,b,w1,w2))
    {
        point A=sym(m1,a-m1,m2-m1),B=sym(m1,b-m1,m2-m1);
        return (seg_cross(a,B,m1,m2) && !seg_cross(a,B,w1,w2) && !seg_cross(A,b,w1,w2));
    }
    return true;
}

int main()
{
    a=read();b=read();w1=read();w2=read();m1=read();m2=read();
    
    cout << (check()?"YES":"NO");
    return 0;
}

Review:

1、求两线段是否有重合部分:

先判相交,再判叉积是否为0

2、判断一点是否在线段上:

用叉积判是否在直线上,再用点积判线段两端是否在其两侧

猜你喜欢

转载自www.cnblogs.com/newera/p/9094568.html