1. 程式人生 > >2017.10.1 國慶清北 D1T2 兩個逗比捉迷藏

2017.10.1 國慶清北 D1T2 兩個逗比捉迷藏

sca sin 計算 foo amp cross bool lib ron

題目描述

你是能看到第二題的friends呢。

——laekov

Hja和Yjq在玩捉迷藏。Yjq躲了起來,Hja要找他。在他們玩遊戲的房間裏,只有一堵不透明的墻和一個雙面的鏡子。Hja和Yjq可以看作平面上坐標分別為(xv,yv)和(xp,yp)的點。墻是一條連接(xw1,yw1)和(xw2,yw2)的線段,鏡子是一條連接(xm1,ym1)和(xm2,ym2)的線段。

如果視線和障礙物有公共點,那麽我們認為視線會被阻擋,無法看見。如果視線和鏡子有公共點,那麽我們認為發生了反射。反射的過程遵循物理規律——入射角等於反射角,且反射光線與入射光線在鏡子同側。也就是說,想要看見對方,Hja和Yjq必須在鏡子的同一側,包括鏡子所在直線上(參見樣例1)。如果視線與鏡子重合,那麽不會發生反射,並且鏡子不被當作障礙物(參見樣例4)。

Hja很想知道他站在原地能否看見Yjq,幫助他解決這個問題。

輸入輸出格式

輸入輸出格式

輸入格式:

第一行兩個數xv,yv,表示Hja的坐標。

第二行兩個數xp,yp表示Yjq的坐標。

第三行四個數xw1,yw1,xw2,yw2,分別表示墻的兩個端點的坐標。

第四行四個數xm1,ym1,?xm2,ym2,分別表示鏡子的兩個端點的坐標。

輸出格式:

如果Hja站在原地能看到Yjq,則輸出"YES",否則輸出"NO"。

輸入輸出樣例

輸入樣例#1:
-1 3
1 3
0 2 0 4
0 0 0 1
輸出樣例#1:
NO
輸入樣例#2:
0 0
1 1
0 1 1 0
-100 -100 -101 -101
輸出樣例#2:

NO
輸入樣例#3:
0 0
1 1
0 1 1 0
-1 1 1 3
輸出樣例#3:
YES
輸入樣例#4:
0 0
10 0
100 100 101 101
1 0 3 0
輸出樣例#4:
YES

說明

對於 100%的數據, 所有坐標均為絕對值不超過 所有坐標均為絕對值不超過 104的整數。輸入線段不會 的整數。輸入線段不會 退化成點,且兩條線段沒有交。 退化成點,且兩條線段沒有交。 Hja和 Yjq的位置不同,且在任何一條線段 的位置不同,且在任何一條線段上

技術分享
  1 /*
  2     叉積 
  3 兩個人如果能看見
  4 1、兩人之間無墻無鏡子(直接看兩人連線與墻和鏡子有無交點) 
  5
2、兩人之間有墻,但是能通過鏡子看到(找兩人視線在鏡子所在直線的交點,判斷交點是否在鏡子上) 6 */ 7 8 #include<cstdio> 9 #include<cstdlib> 10 #include<cstring> 11 #include<cmath> 12 #include<algorithm> 13 using namespace std; 14 const double eps=1e-8; 15 int sgn(double a) 16 { 17 if (fabs(a)<eps) return 0; 18 else 19 { 20 if (a>0.0) return 1; 21 else return -1; 22 } 23 } 24 struct point 25 { 26 double x,y; 27 point(){} 28 point(double a,double b) 29 { 30 x=a;y=b; 31 } 32 void init() 33 { 34 scanf("%lf%lf",&x,&y); 35 } 36 point operator+(const point &a)const 37 { 38 point ans; 39 ans.x=x+a.x; 40 ans.y=y+a.y; 41 return ans; 42 } 43 point operator-(const point &a)const 44 { 45 point ans; 46 ans.x=x-a.x; 47 ans.y=y-a.y; 48 return ans; 49 } 50 point operator*(const double &a)const 51 { 52 point ans; 53 ans.x=x*a; 54 ans.y=y*a; 55 return ans; 56 } 57 void print() 58 { 59 printf("%lf %lf\n",x,y); 60 } 61 }v,p,w1,w2,m1,m2; 62 double cross(point a,point b) 63 { 64 return a.x*b.y-a.y*b.x; 65 } 66 double dot(point a,point b) 67 { 68 return a.x*b.x+a.y*b.y; 69 } 70 bool cross(point p1,point p2,point p3,point p4) 71 { 72 if(sgn(cross(p2-p1,p3-p1))*sgn(cross(p2-p1,p4-p1))==1) return false; 73 if(sgn(cross(p4-p3,p1-p3))*sgn(cross(p4-p3,p2-p3))==1) return false; 74 if(sgn(max(p1.x,p2.x)-min(p3.x,p4.x))==-1) return false; 75 if(sgn(max(p1.y,p2.y)-min(p3.y,p4.y))==-1) return false; 76 if(sgn(max(p3.x,p4.x)-min(p1.x,p2.x))==-1) return false; 77 if(sgn(max(p3.y,p4.y)-min(p1.y,p2.y))==-1) return false; 78 return true; 79 } 80 point getcross(point p1,point p2,point p3,point p4) 81 { 82 double a=p2.y-p1.y; 83 double b=p1.x-p2.x; 84 double c=-p1.x*p2.y+p1.y*p2.x; 85 double d=p4.y-p3.y; 86 double e=p3.x-p4.x; 87 double f=-p3.x*p4.y+p3.y*p4.x; 88 double x=(b*f-c*e)/(a*e-b*d); 89 double y=(a*f-c*d)/(b*d-a*e); 90 return point(x,y); 91 } 92 point calcfoot(point p1,point p2,point p3) 93 { 94 double ratio=dot(p1-p2,p3-p2)/dot(p3-p2,p3-p2); 95 return p2+(p3-p2)*ratio; 96 } 97 bool check() 98 { 99 if(!cross(v,p,w1,w2)) //沒有墻阻擋 100 { 101 if(!cross(v,p,m1,m2)) return true; //也沒有鏡子阻擋 102 if(sgn(cross(m1-v,m2-v))==0&&sgn(cross(m1-p,m2-p)==0)) return true; //與鏡子平行 103 } 104 if(sgn(cross(m2-m1,v-m1))*sgn(cross(m2-m1,p-m1))==1) //計算鏡子所在直線上的折射點 105 { 106 point foot=calcfoot(p,m1,m2); 107 foot=foot*2.0-p; 108 if(cross(v,foot,m1,m2)) //折射點在鏡子上 109 { 110 foot=getcross(v,foot,m1,m2); 111 if(!cross(v,foot,w1,w2)&&!cross(foot,p,w1,w2)) return true; //判斷兩個人的目光是否會被墻打斷 112 } 113 } 114 return false; 115 } 116 int main() 117 { 118 freopen("b.in","r",stdin); 119 freopen("b.out","w",stdout); 120 v.init(); 121 p.init(); 122 w1.init(); 123 w2.init(); 124 m1.init(); 125 m2.init(); 126 if (check()) printf("YES\n"); 127 else printf("NO\n"); 128 return 0; 129 }
View Code

2017.10.1 國慶清北 D1T2 兩個逗比捉迷藏