题目来源:
http://poj.org/problem?id=1584
题意: 给一个多边形, 一个圆心以及半径。 首先判断是否为凸多边形。 如果是凸多边形, 再判断,圆是否在凸多边形内部。
分析:
1) 先判断是否为凸多边形 ,题目给出的顶点是有序的, 即顺时针或是 逆时针。用叉积方向判断。
2) 判断圆在多边形内, 首先判断 圆心是否在多边形内部, 是的话,然后再 判断 圆心到多边形 所有边的 距离d >= r , 即可。
代码如下:
const int Max_N = 1005; const double EPS = 1e-10 ; //---------凸包---- double add(double a, double b){ return (fabs(a + b) < EPS * (fabs(a) + fabs(b))) ? 0 : (a + b) ; } struct Point{ double x , y ; Point(){} Point(double x, double y):x(x),y(y){} double dist(Point p){ return sqrt(add((x - p.x)*(x - p.x) ,(y - p.y )*(y - p.y) )) ; } Point operator -(Point p){ return Point( add(x ,- p.x) , add( y, - p.y) ) ; } double operator ^(Point p){ return add(x * p.y ,- y * p.x ); } }; Point List[Max_N] ; int n; //判断是否为 凸包 bool is_convex(){ int i , left = 0, right = 0; List[n] = List[0] ; List[n+1] = List[1] ; for(i = 0 ; i < n ; i++){ if( ((List[i+1] - List[i])^(List[i+2] - List[i+1])) < 0) right ++ ; else if(((List[i+1] - List[i])^(List[i+2] - List[i+1])) > 0) left ++ ; } if(right==0 || left == 0) return 1 ; return 0; } Point ro; double r; //判断圆心是否在凸包内或凸包边上,在凸包上或内返回1 int inside_convex(){ int i, left = 0 , right = 0; for(i = 0 ; i < n ; i++){ double d = (ro- List[i])^(List[(i+1)%n] - List[i]) ; if(d > 0) left ++; if(d < 0) right ++ ; } if(left == 0 || right == 0) return 1; return 0 ; } // 计算点p到直线p1p2的最短距离 double dist_ptoseg(Point p, Point p1, Point p2){ return fabs((p1-p)^(p2-p)) / (p1.dist(p2)) ; } //判断圆是否在凸多边形内 int cicle_in_convex(){ int i ; List[n] = List[0] ; for(i = 0 ; i< n ; i++){ if(dist_ptoseg(ro , List[i] , List[i+1]) < r ) return 0 ; } return 1; } int main() { while(scanf("%d" , &n) && n >= 3){ scanf("%lf%lf%lf", &r , &ro.x, &ro.y) ; for(int i=0 ; i < n ; i++){ scanf("%lf%lf" , &List[i].x , &List[i].y) ; } if(!is_convex()) puts("HOLE IS ILL-FORMED"); else{ if(inside_convex() && cicle_in_convex()){ puts("PEG WILL FIT") ; } else puts("PEG WILL NOT FIT") ; } } }