码迷,mamicode.com
首页 > 其他好文 > 详细

[Codeforces 32E] Hide-and-Seek

时间:2018-05-26 23:25:09      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:计算几何   在线   name   连线   main   std   namespace   hid   view   

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:

#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、判断一点是否在线段上:

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

[Codeforces 32E] Hide-and-Seek

标签:计算几何   在线   name   连线   main   std   namespace   hid   view   

原文地址:https://www.cnblogs.com/newera/p/9094568.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!