Poj 3335 Rotating Scoreboard (多边形求核)

题目链接:http://poj.org/problem?id=3335

题目中点的顺序均为顺时针。

第一道多边形求交的题,有别人的代码做参考还写的各种水……最惨的是WA的原因居然是调试用的代码没有引掉…………

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

const double STD=1e-8;
const int NUM=110;

struct Point
{
    double x,y;

    Point() {}
    Point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }

    void get()
    {
		scanf("%lf%lf",&x,&y);
	}
}points[NUM],p[NUM],q[NUM];

int n;
double r;
int cCnt,curCnt;

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

void initial ()
{
    for (int i=1;i<=n;i++)
		p[i] = points[i];  
	p[n+1] = p[1];
	p[0] = p[n];
	cCnt = n;
}

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

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

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)    // >=EPS会WA
			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;
}


bool Deal ()  /*半平面相交(直线切割多边形)(点标号从1开始)*/
{             //此时cCnt为最终切割得到的多边形的顶点数,p为存放顶点的数组
	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);
	}
	if (cCnt==0)
		return false;
	return true;
}

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

/*
3
16 2 -1  2 -2  1 -2  0 -1  -1 -2  -2 -2  -2 -1  -1 0  -2 1  -2 2  -1 2  0 1  1 2  2 2  2 1  1 0
17 2 -1  2 -2  1 -2  0 -1  -1 -2  -2 -2  -2 -1  -1 0  -2 1  -2 2  -1 2  0 1  1 2  3 2  3 1  2 1  1 0
17 2 -1  2 -2  1 -2  0 -1  -1 -2  -2 -2  -2 -1  -1 0  -2 1  -2 2  -1 2  0 1  1 2  3 2  3 0  2 1  1 0

Out

YES
YES
NO

*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值