How I Mathematician Wonder What You Are!(poj 3130)

时间:2023-03-08 16:48:26
How I Mathematician Wonder What You Are!(poj 3130)

题意:求问多边形的核(能够看到所有点的点)是否存在。

/*
对于这样的题目,我只能面向std编程了,然而还是不理解。
算法可参考:http://www.cnblogs.com/huangxf/p/4067763.html
*/
#include<cstdio>
#include<iostream>
#include<cmath>
#define N 110
using namespace std;
int m;
double r;
int cCnt,curCnt;////此时cCnt为最终切割得到的多边形的顶点数、暂存顶点个数
struct point{
double x,y;
};
//读入的多边形的顶点(顺时针)、p为存放最终切割得到的多边形顶点的数组、暂存核的顶点
point points[N],p[N],q[N];
void getline(point x,point y,double &a,double &b,double &c){//两点x、y确定一条直线a、b、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=;i<=m;i++) p[i]=points[i];
p[m+]=p[];
p[]=p[m];
cCnt=m;//cCnt为最终切割得到的多边形的顶点数,将其初始化为多边形的顶点的个数
}
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);
point pt;
pt.x=(x.x * v + y.x * u) / (u + v);
pt.y=(x.y * v + y.y * u) / (u + v);
return pt;
}
void cut(double a,double b,double c){
curCnt=;
for(int i=;i<=cCnt;i++){
if(a*p[i].x+b*p[i].y+c>=) q[++curCnt]=p[i];
// c由于精度问题,可能会偏小,所以有些点本应在右侧而没在,故应该接着判断
else {
if(a*p[i-].x+b*p[i-].y+c>){
//如果p[i-1]在直线的右侧的话,则将p[i],p[i-1]形成的直线与已知直线的交点作为核的一个顶点
//(这样的话,由于精度的问题,核的面积可能会有所减少)
q[++curCnt]=intersect(p[i],p[i-],a,b,c);
}
if(a*p[i+].x+b*p[i+].y+c>){
q[++curCnt]=intersect(p[i],p[i+],a,b,c);
}
}
}
for(int i=;i<=curCnt;i++) p[i]=q[i];//将q中暂存的核的顶点转移到p中
p[curCnt+]=q[];p[]=p[curCnt];
cCnt=curCnt;
}
void solve(){
//注意:默认点是顺时针,如果题目不是顺时针,规整化方向
initial();
for(int i=;i<=m;i++){
double a,b,c;
getline(points[i],points[i+],a,b,c);
cut(a,b,c);
}
}
void guizhenghua(){
//规整化方向,逆时针变顺时针,顺时针变逆时针
for(int i=;i<=m;i++) q[i]=points[m-i+];
for(int i=;i<=m;i++) points[i]=q[i];
}
int main(){
int t;
while(cin>>m){
if(m==) break;
for(int i=;i<=m;i++)
scanf("%lf%lf",&points[i].x,&points[i].y);
guizhenghua();
points[m+]=points[];
solve();
if(cCnt<) printf("0\n");
else printf("1\n");
}
return ;
}