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;
}

  

posted on 2012-06-26 22:25  Wizmann  阅读(234)  评论(0)    收藏  举报

导航