UVa 10078 - The Art Gallery

来源:互联网 发布:钢琴谱制作软件 编辑:程序博客网 时间:2024/06/01 22:48

题目:判断多边形是否是凸多边形。

分析:计算几何、凸包。求凸包,判断是否所有点在凸包上,而不是在凸包内即可。

#include <algorithm>#include <iostream>#include <cstdlib>#include <cstdio>#include <cmath>using namespace std;//点结构 typedef struct pnode{double x,y,d;pnode( double a, double b ){x = a;y = b;}pnode(){}}point;point P0,S[55],D[55];//线结构 typedef struct lnode{double x,y,dx,dy;lnode( point a, point b ){x = a.x;y = a.y;dx = b.x-a.x;dy = b.y-a.y;}lnode(){}}line; //叉乘ab*ac double crossproduct( point a, point b, point c ){return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);}//点到点距离 double dist( point a, point b ){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}//坐标排序 bool cmp1( point a, point b ){return (a.x==b.x)?(a.y<b.y):(a.x<b.x);}//级角排序 bool cmp2( point a, point b ){double cp = crossproduct( P0, a, b );if ( cp == 0 ) return a.d < b.d;else return cp > 0;}//计算凸包 int Graham( point *P, int n ){if ( n < 3 ) return n;sort( P+0, P+n, cmp1 );for ( int i = 1 ; i < n ; ++ i )P[i].d = dist( P[0], P[i] );P0 = P[0];sort( P+1, P+n, cmp2 );int top = n;if ( n > 2 ) {top = 1;for ( int i = 2 ; i < n ; ++ i ) {while ( top > 0 && crossproduct( P[top-1], P[top], P[i] ) <= 0 ) -- top;P[++ top] = P[i];}P[++ top] = P[0];}return top;}//点在直线上 bool on( point p, line l ){if ( l.dx*(p.y-l.y)-l.dy*(p.x-l.x) == 0 )if ( (p.x-l.x)*(p.x-l.x-l.dx) <= 0 )if ( (p.y-l.y)*(p.y-l.y-l.dy) <= 0 )return true;return false;}//线段相交 bool cross( line a, line b ){double t1 = 0.0+a.dx*(b.y-a.y)-a.dy*(b.x-a.x);double t2 = 0.0+a.dx*(b.y+b.dy-a.y)-a.dy*(b.x+b.dx-a.x);double t3 = 0.0+b.dx*(a.y-b.y)-b.dy*(a.x-b.x);double t4 = 0.0+b.dx*(a.y+a.dy-b.y)-b.dy*(a.x+a.dx-b.x);return (t1*t2 <= 0)&&(t3*t4 <= 0);}//点在多边形内bool in( point p, point* P, int n ){double d[4][2] = {-5,-5,-5,1005,1005,-5,1005,1005};for ( int t = 0 ; t < 4 ; ++ t ) {line s1 = line( p, point( d[t][0], d[t][1] ) );int  count = 0;for ( int i = 0 ; i < n ; ++ i ) {line s2 = line( P[i], P[i+1] );if ( on( p, s2 ) ) return false;if ( cross( s1, s2 ) ) count ++;if ( on( P[i], s1 ) ) count --;}if ( count%2 == 0 ) return false; }return true;}int main(){int n;while ( scanf("%d",&n) && n ) {for ( int i = 0 ; i < n ; ++ i ) {scanf("%lf%lf",&D[i].x,&D[i].y);S[i] = D[i];}int count = Graham( S, n );int flag  = 0;for ( int i = 0 ; i < n ; ++ i ) if ( count > 2 && in( D[i], S, count ) ) {flag = 1;break;}if ( flag ) printf("Yes\n");else printf("No\n");}return 0;}


原创粉丝点击