您的位置:首页 > 其它

Poj 1279 Art Gallery (多边形求核)

2012-12-27 13:07 281 查看
题目链接:http://poj.org/problem?id=1279

题意:多边形求核的面积

正在进行模板优化工作,不过貌似做了的几题数据都不够强……

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

const double EPS=1e-11;
const int NUM=1510;

int DB (double x)
{
    if (x>EPS)
        return 1;
    if (x<-EPS)
        return -1;
    return 0;
}

struct Point
{
    double x,y;
 
    Point(){}
    Point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }
 
    void get()
    {
		scanf("%lf%lf",&x,&y);
	}
 
    void output()
    {
        printf("(%.2lf %.2lf)",x,y);
    }
 
    Point operator+(Point a)
    {
        return Point(x+a.x,y+a.y);
    }
    Point operator-(Point a)
    {
        return Point(x-a.x,y-a.y);
    }
 
    double operator*(Point a)       //点乘
    {
        return x*a.y-y*a.x;
    }

	double operator^(Point a)       //叉乘
    {
        return x*a.y+y*a.x;
    }

    Point operator*(double t)
    {
        return Point(x*t,y*t);
    }
 
    Point operator/(double t)
    {
        return Point(x/t,y/t);
    }
 
    bool operator==(Point a)
    {
        return DB(x-a.x)==0&&DB(y-a.y)==0;
    }
 
    bool operator!=(Point a)
    {
        return DB(x-a.x)||DB(y-a.y);
    }
}points[NUM],p[NUM],q[NUM];

int n;
double r;
int cCnt,curCnt;

void getline (Point x,Point y,double &a,double &b,double &c)
{
	a = y.y - x.y;
	b = x.x - y.x;
	c = y.x * x.y - x.x * y.y;
}

Point intersect (Point x,Point y,double a,double b,double c)  //相交
{
    double u = fabs(a * x.x + b * x.y + c);
    double v = fabs(a * y.x + b * y.y + c);
    return Point( (x.x * v + y.x * u) / (u + v) , (x.y * v + y.y * u) / (u + v) );
}

/*半平面相交(直线切割多边形)(点标号从1开始)*/
void cut (double a,double b ,double c)
{
	int i;
	curCnt = 0;
	for (i=1;i<=cCnt;i++)
	{
        if (DB(a*p[i].x + b*p[i].y + c) >= 0)
			q[++curCnt] = p[i];
        else
		{
            if (DB(a*p[i-1].x + b*p[i-1].y + c) > 0)
                q[++curCnt] = intersect(p[i],p[i-1],a,b,c);
            if (DB(a*p[i+1].x + b*p[i+1].y + c) > 0)
                q[++curCnt] = intersect(p[i],p[i+1],a,b,c);
        }
    }
    for (i=1;i<=curCnt;i++)
		p[i] = q[i];
    p[curCnt+1] = q[1];
	p[0] = p[curCnt];
    cCnt = curCnt;
}

void GuiZhengHua ()
{
	//规整化方向,逆时针变顺时针,顺时针变逆时针
	for (int i=1;i<(n+1)/2;i++)
		swap(points[i], points[n-i]);
}

double getArea (Point p[],int n)
{
	double ans=0;
	for (int i=0;i<n;i++)
		ans+=p[i]*p[i+1];
	return ans/2;
}

void initial ()
{
    for (int i=1;i<=n;i++)
		p[i] = points[i];  
	p[n+1] = p[1];
	p[0] = p
;
	cCnt = n;
	
	double s=getArea(p,n);     //自动规整化,如果方向确定,可不执行
	if (DB(s)>=0)      //面积为正,说明为逆时针
		GuiZhengHua ();
}

void Deal ()
{
	int i;
	//注意:默认点是顺时针,如果题目不是顺时针,规整化方向  
	initial();
	for (i=1;i<=n;i++)
	{
		double a,b,c;
		getline (points[i],points[i+1],a,b,c);
		cut(a,b,c);
	}       //p[0]~p[cCnt-1]及p[1]~p[cCnt]均存放多边形的核

    /* 
    如果要向内推进r,用该部分代替上个函数 
    for (i=1;i<=n;i++)
	{ 
        Point ta, tb, tt; 
        tt.x = points[i+1].y - points[i].y; 
        tt.y = points[i].x - points[i+1].x; 
        double k = r / sqrt(tt.x * tt.x + tt.y * tt.y); 
        tt.x = tt.x * k; 
        tt.y = tt.y * k; 
        ta.x = points[i].x + tt.x; 
        ta.y = points[i].y + tt.y; 
        tb.x = points[i+1].x + tt.x; 
        tb.y = points[i+1].y + tt.y; 
        double a,b,c; 
        getline(ta,tb,a,b,c); 
        cut(a,b,c); 
    } 
    */
	printf("%.2lf\n",fabs(getArea (p,cCnt)));    //顺时针处理后面积为负,但写成-1.0*会WA……
} 

int main ()
{
	int T;
	scanf("%d",&T);
	while (T--)
	{
		scanf("%d",&n);
		for (int i=1;i<=n;i++)
			points[i].get();
		points[0]=points
;
		points[n+1] = points[1];
		Deal ();
	}
	return 0;
}

/*
input:
1
8
0 0
10 0
5 10
5 15
10 15
10 5
5 5 
5 0

Out
0.00
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: