题目大意:给出两个点,一个双面镜(线段),一面墙(线段),问两个点能否互相直接或间接地看到对方。
思路:两个点要么直接看到对方,这个直接判断一下两点连线是否和墙或者镜子相交就可以了。
两个点通过镜子看到对方,首先两个点必须在镜子同侧,其次,其中一个点的对称点与另一个点的连线必须和镜子有交点,再次,光路上面不能出现墙(就是两条线段和墙判断是否有交)。
求对称点的方法:先求出点A与对称轴L的交点(用向量叉积求面积比的方法)C,然后直接将点A到交点C的向量V累加到C上即可得到对称点。
判断两条线段是否有交点的方法:先求出两条线段所在直线的交点C,然后判断C是不是同时落在两条线段上。
判断一个点是否在线段上的方法:将其x和y分别与线段的左右端点的x、y比较即可。
注意一个坑:光路和墙共线的时候也会被挡住。
#include <cstdio>
#include <cmath>
#include <algorithm>
#define db double
#define eps 1e-8
#define rep(i,j,k) for (i=j;i<=k;i++)
using namespace std;
struct pt{
db x,y;
pt (db X=0,db Y=0) {x=X; y=Y;}
pt operator + (const pt &B) { return pt(x+B.x,y+B.y); }
pt operator - (const pt &B) { return pt(x-B.x,y-B.y); }
db operator * (const pt &B) { return x*B.y-B.x*y; }
pt operator * (const db &c) { return pt(x*c,y*c); }
}A,B,C,D;
struct seg{
pt s,e,v;
seg () {}
seg (pt S,pt E) {s=S; e=E; v=E-S;}
}mir,wal;
pt crs(seg A,seg B)
{
db S1=(B.s-A.s)*A.v,S2=A.v*B.v;
return B.s+(B.v*(S1/S2));
}
bool onit(pt C,seg A)
{
if ((C.x<min(A.s.x,A.e.x)-eps) || (C.x>max(A.s.x,A.e.x)+eps)) return 0;
if ((C.y<min(A.s.y,A.e.y)-eps) || (C.y>max(A.s.y,A.e.y)+eps)) return 0;
return 1;
}
bool cross(seg A,seg B,int md)
{
if (fabs(A.v*B.v)<eps) {
if (md==0) return 0;
if (onit(A.s,B) || onit(A.e,B) || onit(B.s,A) || onit(B.e,A)) return 1;
return 0; //parallel
}
pt C=crs(A,B);
return onit(C,A) && onit(C,B);
}
bool case_1()
{
if (cross(seg(A,B),mir,0)) return 0;
if (cross(seg(A,B),wal,1)) return 0;
return 1;
}
int sgn(db x) {
if (x<-eps) return -1;
if (x>eps) return 1;
return 0;
}
bool case_2()
{
int ca=sgn((A-mir.s)*mir.v),cb=sgn((B-mir.s)*mir.v);
if (!((ca<0 && cb<0) || (ca>0 && cb>0))) return 0;
if (!cross(seg(A,D),mir,0)) return 0;
C=crs(seg(A,D),mir);
if (cross(seg(A,C),wal,1)) return 0;
if (cross(seg(C,B),wal,1)) return 0;
return 1;
}
int main()
{
// freopen("mirror.in","r",stdin);
// freopen("mirror.out","w",stdout);
scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y);
scanf("%lf%lf%lf%lf",&wal.s.x,&wal.s.y,&wal.e.x,&wal.e.y); wal.v=wal.e-wal.s;
scanf("%lf%lf%lf%lf",&mir.s.x,&mir.s.y,&mir.e.x,&mir.e.y); mir.v=mir.e-mir.s;
C=B+pt(-mir.v.y,mir.v.x); C=crs(seg(B,C),mir); D=C+(C-B);
if (case_1() || case_2()) printf("YES\n");
else printf("NO\n");
return 0;
}