http://acm.pku.edu.cn/JudgeOnline/problem?id=3335

问给出的多边形中是否存在一点可以观察到整个多边形。多边形核的判断,这里只需要判断存不存在,即使是一个点也可以.
题目是顺时针给出点的
#include <cmath>
#include
<stdio.h>
#include
<string.h>
#include
<algorithm>
#include
<iostream>
using namespace std;

typedef
double TYPE;
#define MaxPoint 110
#define Epsilon 1e-10 /*验证*///精度的范围 ,根据不同的情况调整精度值
//空间中的点,可以用来作为二维点来用
struct POINT {/*验证*/
TYPE x; TYPE y; TYPE z;
POINT() : x(
0), y(0), z(0) {};
POINT(TYPE _x_, TYPE _y_, TYPE _z_
= 0)
: x(_x_), y(_y_), z(_z_) {};
//要用 G++ 提交 ,可以不用这个
POINT operator =(const POINT &A){
x
= A.x;
y
= A.y;
z
= A.z;
}
};

// 多边形 ,逆时针或顺时针给出x,y
struct POLY {/*验证*/
//n个点
int n;
//x,y为点的指针,首尾必须重合
TYPE * x;
TYPE
* y;
POLY() : n(
0), x(NULL), y(NULL) {};
POLY(
int _n_, const TYPE * _x_, const TYPE * _y_) {
n
= _n_;
x
= new TYPE[n + 1];
memcpy(x, _x_, n
*sizeof(TYPE));
x[n]
= _x_[0];
y
= new TYPE[n + 1];
memcpy(y, _y_, n
*sizeof(TYPE));
y[n]
= _y_[0];
}
};

//判断 x 是正数还是负数
inline int Sign(TYPE x){/*验证*/
return x<-Epsilon?-1:x>Epsilon;
}

void Interect(POINT x,POINT y,TYPE a,TYPE b,TYPE c,int &s,POINT q[]){
TYPE u
=fabs(a*x.x+b*x.y+c);
TYPE v
=fabs(a*y.x+b*y.y+c);
q[
++s].x=(x.x*v+y.x*u)/(u+v);
q[s].y
=(x.y*v+y.y*u)/(u+v);
}
//利用半平面切割
void Cut(TYPE a,TYPE b,TYPE c,int &KarnalPoint,POINT p[])
{
int s=0;
int i;
POINT q[MaxPoint];
for(i=1; i<=KarnalPoint; i++){//遍历所有顶点是否能观察到该边

if(Sign(a* p[i].x+ b*p[i].y+ c)>= 0){//因为线段是顺时针给出的,如果是逆时针就是<=0

q[
++s]= p[i]; //若是则存储
}
else{

if(Sign(a* p[i-1].x+ b* p[i-1].y+ c)> 0)//逆时针就是<0
Interect(p[i-1], p[i], a, b, c, s, q);

if(Sign(a* p[i+1].x+ b* p[i+1].y+ c)> 0)//逆时针就是<0
Interect(p[i+1], p[i], a, b, c, s, q);
}
}
//最后的p数组存放半平面的点集合
for(i=1;i<=s;i++)
p[i]
=q[i];
p[s
+1]=p[1],p[0]=p[s];
KarnalPoint
=s;
}

POLY PolygonKernal(
int n, POINT point[])
{
int KarnalPoint= n;
POINT p[MaxPoint];
//p 的大小和 tr 的大小一样
for(int i= 0; i< n; i++){
p[i
+1]= point[i]; //初始化边界
}
point[n]
= point[0];
p[n
+1]= p[1];
p[
0] = p[n];

TYPE a,b,c;
for(int i=0;i<n;i++){
a
=point[i+1].y- point[i].y ; //计算出相邻两点所在直线ax+by+c=0
b=point[i].x - point[i+1].x;
c
=point[i+1].x* point[i].y- point[i].x* point[i+1].y;
Cut(a, b, c, KarnalPoint, p);
}

TYPE X[MaxPoint],Y[MaxPoint];
for(int i= 0; i< KarnalPoint; i++){
X[i]
= p[i].x;
Y[i]
= p[i].y;
}
POLY poly(KarnalPoint, X, Y);

return poly;
}
int main(){
int n,t;
POINT point[MaxPoint];

scanf(
"%d",&t);
while(t--)
{
scanf(
"%d",&n);
for(int i=0;i<n;i++){
scanf(
"%lf%lf",&point[i].x,&point[i].y);
}
POLY poly
= PolygonKernal(n, point);
if(poly.n== 0) puts("NO");//这里如果有一个点,或者一条线段都可以,所以判断poly.n是不是等于0就行了,不用判断面积
else puts("YES");
}
return 0;
}
posted on 2011-05-10 10:25  敌敌  阅读(557)  评论(0编辑  收藏  举报