POJ 1474 半平面交

//Result:wizmann	1474	Accepted	764K	0MS	G++	3850B	

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <iostream>

#include <algorithm>

#include <cmath>

#include <vector>



using namespace std;



#define print(x) cout<<x<<endl

#define input(x) cin>>x

#define SIZE 128

#define pb push_back



const double eps=1e-10;



inline int zero(double x)

{

	if(x<-eps) return -1;

	else if(fabs(x)<eps) return 0;

	else return 1;

}



struct point

{

	double x,y;

	point(){}

	point(double i_x,double i_y)

	{

		x=i_x;y=i_y;

	}

	

	void setpoint(double i_x,double i_y)

	{

		x=i_x;y=i_y;

	}

	

	friend bool operator == (const point& pa,const point& pb)

	{

		return zero(pa.x-pb.x) && zero(pa.y-pb.y);

	}

};



struct segment

{

	point p1,p2;

	

	segment(){}

	segment(double x1,double y1,double x2,double y2)

	{

		p1.setpoint(x1,y1);

		p2.setpoint(x2,y2);

	}

	segment(point t1,point t2){p1=t1;p2=t2;}

	

	inline void setsegment(point a,point b){p1=a;p2=b;}

	inline void setsegment(double x1,double y1,double x2,double y2)

	{

		p1.setpoint(x1,y1);

		p2.setpoint(x2,y2);

	}

};





struct line

{

	double a,b,c;

	

	friend bool operator == (const line x,const line y)

	{

		if(fabs(x.a-y.a)<eps&&fabs(x.b-y.b)<eps&&fabs(x.c-y.c)<eps) return true;

		else return false;

	}	

	inline void setline(double ta,double tb,double tc)

	{

		a=ta;b=tb;c=tc;

	}

};





double xmult(point sp,point ep,point op)

{

	return((sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x));

}



line makeLine(point p1,point p2)

{

	line res;

	int sig=1;

	res.a=p2.y-p1.y;

	if(res.a<0)

	{

		sig=-1;

		res.a=sig*res.a;

	}

	res.b=sig*(p1.x-p2.x);

	res.c=sig*(p1.y*p2.x-p2.y*p1.x);

	return res;

}



line makeLine(segment s)

{

	return makeLine(s.p1,s.p2);

}



bool lineIntersect(line l1,line l2,point &p)

{

	double d=l1.a*l2.b-l2.a*l1.b;

	if(fabs(d)<eps) return false;

	else

	{

		p.x = (l2.c*l1.b-l1.c*l2.b)/d;

		p.y = (l2.a*l1.c-l1.a*l2.c)/d;

		return true;

	}

}



bool segIntersect(segment l1,segment l2,point &p)

{

	if((max(l1.p1.x,l1.p2.x)>=min(l2.p1.x,l2.p2.x))&&

	   (max(l1.p1.y,l1.p2.y)>=min(l2.p1.y,l2.p2.y))&&

	   (max(l2.p1.x,l2.p2.x)>=min(l1.p1.x,l1.p2.x))&&

	   (max(l2.p1.y,l2.p2.y)>=min(l1.p1.y,l1.p2.y))&&//快速排斥实验

	   fabs((xmult(l1.p1,l2.p1,l2.p2)*xmult(l1.p2,l2.p1,l2.p2))<=eps)&&

	   fabs((xmult(l2.p1,l1.p1,l1.p2)*xmult(l2.p2,l1.p1,l1.p2))<=eps))//跨立实验

	{

		lineIntersect(makeLine(l1),makeLine(l2),p);

		return true;

	}

	else return false;

}





struct polygen

{

	point pvec[SIZE];

	point core[SIZE];

	int sz;//kernel points

	polygen(){sz=0;}

	

	inline void push_point(const point& p)

	{

		pvec[sz++]=p;

	}

	

	void Cut(segment s)

	{

		int q=0;

		//print(sz);

		for(int i=0;i<sz;i++)

		{

			if(xmult(pvec[i],s.p2,s.p1)>=0)

			{

				//因为线段是顺时针给出的,如果是逆时针就是<=0

				core[q++]=pvec[i]; //若是则存储

			}

			else

			{

				point cp;

                if(xmult(pvec[i],s.p2,s.p1) * xmult(pvec[(i+1)%sz],s.p2,s.p1)<0)

                {

					point cp;

					line l1=makeLine(s);

					line l2=makeLine(pvec[i],pvec[(i+1)%sz]);

					lineIntersect(l1,l2,cp);

					core[q++]=cp;

				}

			}

		}

		//最后的p数组存放半平面的点集合

		for(int i=0;i<q;i++)

		{

			pvec[i]=core[i];

		}

		//print("CORE: "<<core.size());

		sz=q;

		//print(sz);

	}

	

	void getKernel()

	{

		int n=sz;

		point p[SIZE];

		for(int i=0;i<n;i++) p[i]=pvec[i];

		for(int i=0;i<n;i++)

		{

			segment s(p[i],p[(i+1)%n]);

			Cut(s);

		}

	}

};



int n;

polygen poly;



int main()

{

	double a,b;

	int cas=1;

	while(input(n) && n)

	{

		poly=polygen();

		for(int i=0;i<n;i++)

		{

			scanf("%lf%lf",&a,&b);

			poly.push_point(point(a,b));

		}

		poly.getKernel();

		printf("Floor #%d\n",cas++);

		if(poly.sz>0) print("Surveillance is possible.");

		else print("Surveillance is impossible.");

		puts("");

	}

	return 0;

}

  

你可能感兴趣的:(poj)