题目链接:poj 1066
题意:
给你一个100*100的正方形,再给你n条线(墙),保证线段一定在正方形内且端点在正方形边界(外墙),最后给你一个正方形内的点(保证不再墙上)
告诉你墙之间(包括外墙)围成了一些小房间,在小房间内可以从房间边界(墙)的中点走过这堵墙,问你从给定的点走到外墙外最少走过的墙数。
题解:直接把中心点与边界点连成线段,并判断有多少条线段与之相交,最小的相交数就是答案,详情见代码。
///把中心点与边界上的点连线,遍历n条线段,有多少次相交,就要破多少个墙
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
struct point{
double x,y;
point(){}
point(double _x,double _y){
x=_x;y=_y;
}
};
struct Line{
point a,b;
Line(){}
Line(point _a,point _b){
a=_a;b=_b;
}
};
point operator + (point a,point b) {return point(a.x+b.x,a.y+b.y);}
point operator - (point a,point b) {return point(a.x-b.x,a.y-b.y);}
point operator * (point a,double p) { return point(a.x*p,a.y*p);}
point operator / (point a,double p){ return point(a.x/p,a.y/p);}
bool operator < (const point &a,const point &b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
const double esp=1e-8;
int dcmp(double x){
if(fabs(x)<1e-8) return 0;
else return x<0?-1:1;
}
bool operator ==(const point &a,const point &b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Cross(point a,point b){ return a.x*b.y-a.y*b.x;}
bool isCross(point s1,point e1,point s2,point e2)///判断线段相交判定
{
///第一步,快速排斥实验
if(!(min(s1.x,e1.x)<=max(s2.x,e2.x)&&min(s2.x,e2.x)<=max(s1.x,e1.x)&&
min(s1.y,e1.y)<=max(s2.y,e2.y)&&min(s2.y,e2.y)<=max(s1.y,e1.y))) return false;
///首先判断向量s2e2 跨立 向量s1e1
double c1=Cross(s2-s1,e1-s1),c2=Cross(e1-s1,e2-s1);
///再次判断向量s1e1 跨立 向量 s2e2
double c3=Cross(s1-s2,e2-s2),c4=Cross(e2-s2,e1-s2);
///==0表示,相交于端点也认定为相交
// printf("c1=%f,c2=%f,c3=%f,c4=%f\n",c1,c2,c3,c4);
if(dcmp(c1*c2)>0&&dcmp(c3*c4)>0) return true;
return false;
}
Line line[50];
int n;
int check(point s1,point e1)
{
int item=0;
for(int i=1;i<=n;i++)
{
if(isCross(s1,e1,line[i].a,line[i].b)) item++;
///此题相交于端点不算
}
return item;
}
int main()
{
while(~scanf("%d",&n))
{
double x1,y1,x2,y2;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[i]=Line(point(x1,y1),point(x2,y2));
}
point center;
scanf("%lf%lf",¢er.x,¢er.y);
if(n==0){
printf("Number of doors = 1\n");continue;
}
int mins=INF;
for(int i=1;i<=n;i++) ///遍历边界的点
{
mins=min(mins,check(line[i].a,center));
mins=min(mins,check(line[i].b,center));
}
mins=min(mins,check(point(0,0),center)); ///四个顶角
mins=min(mins,check(point(0,100),center));
mins=min(mins,check(point(100,0),center));
mins=min(mins,check(point(100,100),center));
printf("Number of doors = %d\n",mins+1);
}
return 0;
}