A Round Peg in a Ground Hole--POJ 1584
1、题目类型:模拟、计算几何。
2、解题思路:(1)检测是否为凹多边形;(2)检测圆心是否在凸多边形内部;(3)检测圆心到多边形所有边的距离是否小于半径 (具体见实现代码)。
3、注意事项:注意多边形的顺时针和逆时针,由于上的是模板,所以细节考虑并不多。
4、实现方法:
#include<iostream>
#include<cmath>
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
using namespace std;
struct Point
{
double x,y;
};
int n;
double r;
Point P[160];
Point c;
//检测是否为凹多边形: *p表示为多边形序列,n表示为多边形顶点数
int Check1(Point *p,int n)
{
int i,j,k,flag = 0;
double z;
if (n < 3)
return (0);
for (i=0;i<n;i++)
{
j = (i + 1) % n;
k = (i + 2) % n;
z = (p[j].x - p[i].x) * (p[k].y - p[j].y);
z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);
if (z < 0)
flag |= 1;
else if (z > 0)
flag |= 2;
if (flag == 3)
return 0;
}
if (flag != 0)
return 1;
else
return 0;
}
// 检测点是否在多边形内: *polygon表示为多边形序列,n表示为多边形顶点数,p表示为点
int Check2(Point *polygon,int N,Point p)
{
int i,counter = 0;
double xinters;
Point p1,p2;
p1 = polygon[0];
for (i=1;i<=N;i++)
{
p2 = polygon[i % N];
if (p.y > MIN(p1.y,p2.y))
{
if (p.y <= MAX(p1.y,p2.y))
{
if (p.x <= MAX(p1.x,p2.x))
{
if (p1.y != p2.y)
{
xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
if (p1.x == p2.x || p.x <= xinters)
counter++;
}
}
}
}
p1 = p2;
}
if (counter % 2 == 0)
return 1;
else
return 0;
}
//计算点到线段的最短距离:p1,p2表示线段的两点,q表示距离点
double Mindistance(Point p1,Point p2,Point q)
{
int flag=1;
double k;
Point s;
if (p1.x==p2.x) {s.x=p1.x;s.y=q.y;flag=0;}
if (p1.y==p2.y) {s.x=q.x;s.y=p1.y;flag=0;}
if (flag)
{
k=(p2.y-p1.y)/(p2.x-p1.x);
s.x=(k*k*p1.x+k*(q.y-p1.y)+q.x)/(k*k+1);
s.y=k*(s.x-p1.x)+p1.y;
}
if (MIN(p1.x,p2.x)<=s.x&&s.x<=MAX(p1.x,p2.x))
return sqrt((q.x-s.x)*(q.x-s.x)+(q.y-s.y)*(q.y-s.y));
else
return MIN(sqrt((q.x-p1.x)*(q.x-p1.x)+(q.y-p1.y)*(q.y-p1.y)),
sqrt((q.x-p2.x)*(q.x-p2.x)+(q.y-p2.y)*(q.y-p2.y)));
}
int Check3()
{
int i;
P[n].x=P[0].x;
P[n].y=P[0].y;
for(i=0;i<n;i++)
{
if(Mindistance(P[i],P[i+1],c)<r)
return 0;
}
return 1;
}
void Solve()
{
if(!Check1(P,n))
{
cout<<"HOLE IS ILL-FORMED"<<endl;
return ;
}
if(Check2(P,n,c))
{
cout<<"PEG WILL NOT FIT"<<endl;
return ;
}
if(!Check3())
{
cout<<"PEG WILL NOT FIT"<<endl;
return ;
}
else
{
cout<<"PEG WILL FIT"<<endl;
return ;
}
}
int main()
{
int i;
while(cin>>n && n>=3)
{
cin>>r>>c.x>>c.y;
for(i=0;i<n;i++)
{
cin>>P[i].x>>P[i].y;
}
Solve();
}
return 0;
}