UVA 10078 The Art Gallery(凸多边形判定)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1019
题意:
给你一个多边形,按时针顺序(顺时针或逆时针)给出这个多边形的所有顶点,问你该多边形内是否存在临界点? 临界点就是当你站在多边形内的那点处,你想看到多边形内部的所有其他边时,视野会被挡住.
分析:
其实临界点只有凹多边形才会有,凸多边形不可能存在临界点.所以本题直接转化为判断一个多边形是不是凸多边形的问题. 有下面两种方法解决:
1. 如果多边形是凸多边形,那么它所有的边都是往相同方向转的.假设现在有i边,i+1边,i+2边.所以i边与i+1边的叉积符号必然与i边与i+1边的叉积符号同号.如果i+1边在第i条边的基础上往左转,那么它们的向量叉积>0.否则<0. 如果它们共线,那么它们向量叉积==0.
2. (由于题目给的点都是多边形的顶点)我们只要求该点集的凸包,看看凸包(最大点集)的大小是否==原始点集的大小即可. 如果不等,那么说明有些点不在凸包上,那么必然该多边形不是凸多边形.(当然对比面积也行)
AC代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
//精度控制
const double eps=1e-10;
int dcmp(double x)
{
if(fabs(x)<eps) return 0;
return x<0?-1:1;
}
//点
struct Point
{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
};
//向量
typedef Point Vector;
//点-点==向量
Vector operator-(Point A,Point B)
{
return Vector(A.x-B.x,A.y-B.y);
}
//叉积
double Cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
//判断多边形是否是凸的
bool IsConvexPolygon(Point *p,int n)
{
for(int i=0;i<n;i++)
{
double c1=Cross(p[(i+1)%n]-p[i], p[(i+2)%n]-p[(i+1)%n]);
double c2=Cross(p[(i+2)%n]-p[(i+1)%n], p[(i+3)%n]-p[(i+2)%n]);
if(dcmp(c1)*dcmp(c2)<0) return false;
}
return true;
}
const int maxn=50+5;
Point p[maxn];
int main()
{
int n;
while(scanf("%d",&n)==1 && n)
{
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
printf("%s\n",IsConvexPolygon(p,n)?"No":"Yes");
}
return 0;
}