题目大意:就是给一些点的坐标(in order),判断它们是否构成凸包,如果是构成凸包,在判断给定圆是否在凸包内(圆心位于凸包内,且半径不大于圆心与凸包边的最小距离)。
分析:判断圆心是否在多边形内,采用环顾角的方法,若求得的环顾角为 2π 或 −2π 则说明在多边形内(具体见lrj的黑书第三章)。
代码:
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const double EPS=1e-8;
const double INF=999999.0;
const double PI=4*atan(1);
int n;
int dblcmp(double x){
return fabs(x)<EPS?0:(x>0?1:-1);
}
struct Point;
typedef Point Vector;
struct Point{
double x,y;
Point(){}
Point(double xx,double yy):x(xx),y(yy){}
Vector operator -(Point p){
return Vector(x-p.x,y-p.y);
}
double operator ^(Vector v){ //向量叉积
return x*v.y-y*v.x;
}
double operator *(Vector v){ //向量点积
return x*v.x+y*v.y;
}
double module(){ //向量的模
return sqrt(x*x+y*y);
}
};
struct Segment{
Point p1,p2;
Segment(){}
Segment(Point pp1,Point pp2):p1(pp1),p2(pp2){}
double dist(Point p){ //点到线段的距离
double area=fabs((p1-p)^(p2-p));
return area/(p1-p2).module();
}
double angle(Point p){ //线段环顾角
Vector v1=p1-p,v2=p2-p;
return acos((v1*v2)/(v1.module()*v2.module()));
}
};
struct Polygon{
vector<Point> p;
vector<Segment> e;
void getVertex(){
double x,y;
for(int i=0;i<n;++i){
cin>>x>>y;
p.push_back(Point(x,y));
}
}
bool buildEdge(){
int direction_old=0;
int direction_new;
for(int i=0;i<n;++i){
e.push_back(Segment(p[i],p[(i+1)%n]));
if(i){
if(direction_new=dblcmp((p[i]-p[i-1])^(p[(i+1)%n]-p[i-1]))){
if(abs(direction_new-direction_old)>1) return false; //不为凸包
else direction_old=direction_new;
}
}
}
return true;
}
bool inPolygon(Point p){ //是否位于多边形内
double angle_sum=0.0;
for(int i=0;i<n;++i){
angle_sum+=e[i].angle(p);
}
if(!dblcmp(fabs(angle_sum)-2*PI)) return true;
else return false;
}
double minDist(Point p){ //点到多边形边的最短距离
double min_dist=INF;
for(int i=0;i<n;++i){
min_dist=min(min_dist,e[i].dist(p));
}
return min_dist;
}
};
struct Circle{
double r,x,y;
void buildCircle(){
cin>>r>>x>>y;
}
void output(Polygon& p){
if(p.buildEdge()){
if(p.inPolygon(Point(x,y))&&dblcmp(p.minDist(Point(x,y))-r)>=0){
cout<<"PEG WILL FIT"<<endl;
}
else cout<<"PEG WILL NOT FIT"<<endl;
}
else cout<<"HOLE IS ILL-FORMED"<<endl;
}
};
int main(){
ios::sync_with_stdio(false);
while(cin>>n,n>=3){
Circle circle;
Polygon polygon;
circle.buildCircle();
polygon.getVertex();
circle.output(polygon);
}
return 0;
}