首页 > 代码库 > POJ 3335 Rotating Scoreboard 半平面交求多边形内核

POJ 3335 Rotating Scoreboard 半平面交求多边形内核

题目大意:多边形求内核模板题


思路:半平面交,我用的是O(nlogn)的半平面交,但是有一个问题,就是当多边形内核是一个点的时候,半平面交所得到的答案是空集合,但是输出应该是yes,实在没有什么好的解决方法,最后只能把所有直线向右移动,然后在求内核。但是这样做eps的不同取值有的时候能A有的时候不能A。有没有什么好的解决方法啊!!!求解答啊!!!


CODE:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 110
#define EPS 1e-12
#define DCMP(a)	(fabs(a) < EPS ? true:false)
using namespace std;

struct Point{
	double x,y;
	
	Point(double _ = 0.0,double __ = 0.0):x(_),y(__) {}
	Point operator -(const Point &a)const {
		return Point(x - a.x,y - a.y);
	}
	Point operator +(const Point &a)const {
		return Point(x + a.x,y + a.y);
	}
	Point operator *(double a)const {
		return Point(x * a,y * a);
	}
	void operator += (const Point &a) {
		x += a.x, y += a.y;
	}
	void Read() {
		scanf("%lf%lf",&x,&y);
	}
}point[MAX],p[MAX],polygon[MAX];
struct Line{
	Point p,v;
	double alpha;
	
	bool operator <(const Line &a)const {
		return alpha < a.alpha;
	}
	Line(Point _,Point __):p(_),v(__) {
		alpha = atan2(v.y,v.x);
	}
	Line() {}
}line[MAX],q[MAX];

int cases;
int points,lines;

inline void Initialize();
inline void MakeLine(const Point &a,const Point &b);

inline double Cross(const Point &a,const Point &b);
inline bool OnLeft(const Line &l,const Point &p);
inline bool HalfPlaneIntersection();
inline Point GetIntersection(const Line &a,const Line &b);

int main()
{
	for(cin >> cases;cases; --cases) {
		scanf("%d",&points);
		Initialize();
		for(int i = 1;i <= points; ++i)
			point[i].Read();
		for(int i = points;i > 1; --i)
			MakeLine(point[i],point[i - 1]);
		MakeLine(point[1],point[points]);
		sort(line + 1,line + lines + 1);
		bool ans = HalfPlaneIntersection();
		if(ans)	puts("YES");
		else	puts("NO");
	}	
	return 0;
}

inline void Initialize()
{
	lines = 0;
}

inline void MakeLine(const Point &a,const Point &b)
{
	Point p = a;
	Point v = b - a;
	p += Point(v.y, -v.x) * (EPS * 0.5);
	line[++lines] = Line(p, v);
}

inline double Cross(const Point &a,const Point &b)
{
	return a.x * b.y - a.y * b.x;
}

inline bool OnLeft(const Line &l,const Point &p)
{
	return Cross(l.v,p - l.p) > 0;
}

inline Point GetIntersection(const Line &a,const Line &b)
{
	Point u = a.p - b.p;
	double temp = Cross(b.v,u) / Cross(a.v,b.v);
	return a.p + a.v * temp;
}

inline bool HalfPlaneIntersection()
{
	int front = 1,tail = 1;
	q[1] = line[1];
	for(int i = 2;i <= lines; ++i) {
		while(front < tail && !OnLeft(line[i],p[tail - 1]))	--tail;
		while(front < tail && !OnLeft(line[i],p[front]))	++front;
		if(DCMP(Cross(line[i].v,q[tail].v)))
			q[tail] = OnLeft(q[tail],line[i].p) ? line[i]:q[tail];
		else	q[++tail] = line[i];
		if(front < tail)	p[tail - 1] = GetIntersection(q[tail],q[tail - 1]);
	}
	while(front < tail && !OnLeft(q[front],p[tail - 1]))	--tail;
	return front < tail;
}


POJ 3335 Rotating Scoreboard 半平面交求多边形内核