1. 程式人生 > >[Codeforces 32E] Hide-and-Seek

[Codeforces 32E] Hide-and-Seek

sin IV con style str hide eal pac its

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