Description
A recent factory run of computer desks were flawed when an automatic grinding machine was mis-programmed. The result is an irregularly shaped hole in one piece that, instead of the expected circular shape, is actually an irregular polygon. You need to figure out whether the desks need to be scrapped or if they can be salvaged by filling a part of the hole with a mixture of wood shavings and glue.
There are two concerns. First, if the hole contains any protrusions (i.e., if there exist any two interior points in the hole that, if connected by a line segment, that segment would cross one or more edges of the hole), then the filled-in-hole would not be structurally sound enough to support the peg under normal stress as the furniture is used. Second, assuming the hole is appropriately shaped, it must be big enough to allow insertion of the peg. Since the hole in this piece of wood must match up with a corresponding hole in other pieces, the precise location where the peg must fit is known.
Write a program to accept descriptions of pegs and polygonal holes and determine if the hole is ill-formed and, if not, whether the peg will fit at the desired location. Each hole is described as a polygon with vertices (x1, y1), (x2, y2), . . . , (xn, yn). The edges of the polygon are (xi, yi) to (xi+1, yi+1) for i = 1 . . . n − 1 and (xn, yn) to (x1, y1).
Input
Line 1 < nVertices > < pegRadius > < pegX > < pegY >
number of vertices in polygon, n (integer)
radius of peg (real)
X and Y position of peg (real)
n Lines < vertexX > < vertexY >
On a line for each vertex, listed in order, the X and Y position of vertex The end of input is indicated by a number of polygon vertices less than 3.
Output
HOLE IS ILL-FORMED if the hole contains protrusions
PEG WILL FIT if the hole contains no protrusions and the peg fits in the hole at the indicated position
PEG WILL NOT FIT if the hole contains no protrusions but the peg will not fit in the hole at the indicated position
Sample Input
5 1.5 1.5 2.0 1.0 1.0 2.0 2.0 1.75 2.0 1.0 3.0 0.0 2.0 5 1.5 1.5 2.0 1.0 1.0 2.0 2.0 1.75 2.5 1.0 3.0 0.0 2.0 1
Sample Output
HOLE IS ILL-FORMED PEG WILL NOT FIT
題目大意:
給定n個連續的點,以及一個圓的圓心和半徑,問圓是否在多邊形內部,如果順序給定的點不能組成凸多邊形,則輸出“Hole IS ILL-FORMED”,如果圓在多邊形內部則輸出“PEG WILL FIT”,否則輸出“PEG WILL NOT FIT”。
解題思路:
1.先跑一遍凸包,如果給定的點全在凸包上說明給定的點可以組成凸多邊形,否則則不能組成凸多邊形,輸出“HOLE IS ILL-FORMED”
2.經過步驟1後,判斷給定圓心是否在凸多邊形內,用環顧角來判斷,依次順序枚舉相鄰的點組成邊,與給定的圓心形成夾角,可以運用公式,(不好寫公式,編輯不出來,看代碼吧。。。),如果環顧角之和爲+360或-360(要寫成弧度即2PI),則圓心在多邊形內部,否則說明在多邊形上或外部,輸出“PEG WILL NOT FIT”
3.經過上述步驟後,確定了給定點可以組成凸多邊形且圓心在多邊形內部,然後就是判定圓是不是在多邊形內部,那就依次枚舉圓心到每條邊的距離,如果都大於等於圓的半徑,則圓在多邊形內部,輸出“PEG WILL FIT”,否則輸出“PEG WILL NOT FIT”,同樣,點到線段的計算公式見代碼。。 = =
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cmath>
#include <map>
#include <set>
#include <bitset>
#include <ctime>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <list>
#define STD_REOPEN() freopen("../in.in","r",stdin)
#define STREAM_REOPEN fstream cin("../in.in")
#define INF 0x3f3f3f3f
#define _INF 63
#define eps 1e-8
#define MAX_V 100010
#define MAX_P 110
#define MAX_E 10010
#define MAX 32000
#define MOD_P 3221225473
#define MOD 9901
using namespace std;
struct Point
{
double x,y;
Point(){}
Point(double a,double b):x(a),y(b){}
Point operator - (const Point a)const //求向量
{
return Point(x-a.x,y-a.y);
}
double operator * (const Point a)const //點乘
{
return x*a.x+y*a.y;
}
double operator ^ (const Point a)const //叉乘
{
return (x*a.y)-(y*a.x);
}
double operator & (const Point a)const //兩點間距離
{
return sqrt((x-a.x)*(x-a.x)+(y-a.y)*(y-a.y));
}
bool operator < (const Point a)const
{
if(y==a.y)
return x<a.x;
return y<a.y;
}
}s[1010];
double rx,ry,r;
const double PI=acos(-1.0);
int dcmp(double x)
{
return fabs(x)<eps?0:(x<0?-1:1);
}
double getAngle(Point p,Point a,Point b) //獲取點p到線段ab兩端點形成的夾角
{
return acos((Point(a-p)*Point(b-p))/((p&a)*(p&b)));
}
double getDistance(Point p,Point a,Point b) //求點p到線段ab的距離
{
if(dcmp((p-a)*(b-a))<0)
return p&a;
if(dcmp((p-b)*(a-b))<0)
return p&b;
return fabs(((a-p)^(b-p))/(a&b));
}
int GrahamScan(int n) //求凸包,返回01表示無法形成凸多邊形,0表示圓心在凸多邊形之外或圓不在多邊形之內,1表示圓在多邊形內
{
sort(s,s+n);
Point res[1010];
int top=0;
for(int i=0;i<n;i++)
{
while(top>=2&&(Point(res[top-1]-res[top-2])^Point(s[i]-res[top-2]))<0)
top--;
res[top++]=s[i];
}
int len=top+1;
for(int i=n-2;i>=0;i--)
{
while(top>=len&&(Point(res[top-1]-res[top-2])^Point(s[i]-res[top-2]))<0)
top--;
res[top++]=s[i];
}
if(top-1<n) //凸包內頂點數(這裏起始點有重複)小於總點數,返回-1
return -1;
double cnt=0;
for(int i=0;i<top-1;i++)
cnt+=getAngle(Point(rx,ry),res[i],res[i+1]);
//cout<<cnt<<endl;
if(!(dcmp(cnt-2*PI)==0||dcmp(cnt+2*PI)==0)) //環顧角絕對值不等於2PI
return 0;
bool isOK=true;
for(int i=0;i<top-1;i++)
if(dcmp(getDistance(Point(rx,ry),res[i],res[i+1])-r)<0) //圓心到邊的距離小於半徑
{
isOK=false;
break;
}
return isOK?1:0;
}
int main()
{
//STD_REOPEN();
int n;
while(scanf("%d",&n),n>=3)
{
scanf("%lf %lf %lf",&r,&rx,&ry);
for(int i=0;i<n;i++)
scanf("%lf %lf",&s[i].x,&s[i].y);
int ans=GrahamScan(n);
if(ans==-1)
printf("HOLE IS ILL-FORMED\n");
else if(ans==0)
printf("PEG WILL NOT FIT\n");
else
printf("PEG WILL FIT\n");
}
return 0;
}