POJ_1584
这个题目思路是比较直接的,首先去判断这个多边形是否为凹多边形,如果不是凹多边形,就去判断圆是否在多边形内。
在判断多边形是否为凹多边形时,可以将相邻的两个线段做叉积,从而判断在沿四边形走时是否只向左或者只向右转,从而说明这个多边形是否为凹多边形。从discuss里面看到说有的数据相邻的两个线段是共线的,要注意一下这样的情况。
在判断圆是否在多边形内时,可以分两步,第一步判断圆心是否在多边形内,第二步判断圆和多边形是否“相割”。
判断圆心是否在多边形内时,可以先规定好多边形的正方向,然后看这个点是否在所有线段向量的同一侧。
判断圆和多边形是否“相割”时,可以先判断是否有多边形的顶点在圆的内部,如果存在这样的点,那么圆和多边形肯定是“相割”的。做完上一步判断后,对任意圆心到该线段的距离小于半径的线段还剩两种情况,要么和圆“相割”,要么在圆外,但线段的两个端点都是在圆外的,所以我们可以先找到这个线段的法向量,然后去判断线段的两个端点是否分布在以圆心为起点且与法向量同向的向量的异侧,如果分布在异侧,就可以说明这个线段是和圆“相割”的。
不过,上面所说的判断圆和多边形是否“相割”的方法是针对任意一个简单多边形的,但由于这个题目后面就一定是非凹多边形了,所以直接判断圆心到每条线段的距离是否小于R即可。点到线段的距离可以用有向面积的绝对值除以线段的长度得到。
#include<stdio.h>
#include<string.h>
#define MAXD 160
#define zero 1e-8
int N;
double R, X, Y, x[MAXD], y[MAXD];
void init()
{
int i, j, k;
scanf("%lf%lf%lf", &R, &X, &Y);
for(i = 0; i < N; i ++)
scanf("%lf%lf", &x[i], &y[i]);
x[N] = x[0], y[N] = y[0];
}
double fabs(double x)
{
return x < 0 ? -x : x;
}
int dcmp(double x)
{
if(fabs(x) < zero)
return 0;
if(x < 0)
return -1;
return 1;
}
double det(double x1, double y1, double x2, double y2)
{
return x1 * y2 - x2 * y1;
}
int check1()
{
int i, j, k, st = 0;
for(i = 1; i < N; i ++)
{
k = dcmp(det(x[i] - x[i - 1], y[i] - y[i - 1], x[i + 1] - x[i], y[i + 1] - y[i]));
if(!st)
st = k;
if(k && st != k)
return 0;
}
return 1;
}
int inpolygon()
{
int i, j, k, st;
st = dcmp(det(x[1] - x[0], y[1] - y[0], X - x[0], Y - y[0]));
if(st == 0)
return 0;
for(i = 1; i < N; i ++)
{
k = dcmp(det(x[i + 1] - x[i], y[i + 1] - y[i], X - x[i], Y - y[i]));
if(k != st)
return 0;
}
return 1;
}
int check2()
{
int i, j, k;
double t, t1, t2, dx, dy;
if(!inpolygon())
return 0;
for(i = 0; i < N; i ++)
if(dcmp((x[i] - X) * (x[i] - X) + (y[i] - Y) * (y[i] - Y) - R * R) == -1)
return 0;
for(i = 0; i < N; i ++)
{
t = det(x[i] - X, y[i] - Y, x[i + 1] - X, y[i + 1] - Y);
t = t * t / ((x[i + 1] - x[i]) * (x[i + 1] - x[i]) + (y[i + 1] - y[i]) * (y[i + 1] - y[i]));
if(dcmp(t - R * R) == -1)
{
if(dcmp(y[i] - y[i + 1]) == 0)
dx = 0, dy = 1;
else
dx = 1, dy = (x[i] - x[i + 1]) / (y[i + 1] - y[i]);
}
t1 = dcmp(det(dx, dy, x[i] - X, y[i] - Y));
t2 = dcmp(det(dx, dy, x[i + 1] - X, y[i + 1] - Y));
if(t1 * t2 < 0)
return 0;
}
return 1;
}
void solve()
{
int i, j, k;
if(!check1())
printf("HOLE IS ILL-FORMED\n");
else
{
if(check2())
printf("PEG WILL FIT\n");
else
printf("PEG WILL NOT FIT\n");
}
}
int main()
{
for(;;)
{
scanf("%d", &N);
if(N < 3)
break;
init();
solve();
}
return 0;
}