刚开始没有考虑四顶点和各端点的区别,wa了
这次把一些基本函数自己研究透原理了,手打了一遍
/*该题中这种直接由直接构成的多边形一定是凸多边形
因为该题中的线段都是跨越整个正方形的,所以如果从目标点连一条射线出去 ,那么从其他地方绕路过去也必然会经过该线段
本来需要枚举每边界上相邻两点的中点的,但从中点穿过也相当于从端点穿过,所以直接枚举端点就可以了
*/
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
const double EPS=1e-8;
int sgn(double x) {
if (fabs(x)<EPS) return 0;
if (x<0) return -1;
return 1;
}
struct Point {
double x,y;
Point() {}
Point(double _x,double _y) {
x=_x;
y=_y;
}
Point operator - (const Point &b) const {
return Point(x-b.x,y-b.y);
}
double operator ^ (const Point &b) const {
return x*b.y-y*b.x;
}
};
struct Line {
Point s,e;
Line() {}
Line(Point _s,Point _e) {
s=_s;
e=_e;
}
};
bool inter(Line l1,Line l2) {
return
//快速排斥实验
max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x) &&//右界大于左界
max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y) &&//上界要大于下界
max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y) &&
//跨立实验
sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=0 &&
sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=0;
}
Line l[100];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n;
double x1,y1,x2,y2;
Point t;
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
l[i]=Line(Point(x1,y1),Point(x2,y2));
}
scanf("%lf%lf",&t.x,&t.y);
l[n+1]=Line(Point(0,0),Point(0,100));
l[n+2]=Line(Point(0,100),Point(100,100));
l[n+3]=Line(Point(100,100),Point(100,0));
l[n+4]=Line(Point(100,0),Point(0,0));
Point p;
int cnt=0;
int ans=100000;
for(int i=1;i<=n+4;i++) {
cnt=0;
p=l[i].s;
for(int j=1;j<=n;j++) {
if (inter(Line(p,t),l[j])) cnt++;
}
//因为边界上的点本来就已经在一条线段上了,所以不需要加+1,而四顶点还要加上最后一层强需要的点
if (i>n) ans=min(cnt+1,ans);
else ans=min(cnt,ans);
cnt=0;
p=l[i].e;
for(int j=1;j<=n;j++) {
if (inter(Line(p,t),l[j])) cnt++;
}
if (i>n) ans=min(cnt+1,ans);
else ans=min(cnt,ans);
}
printf("Number of doors = %d\n",ans);
return 0;
}