POJ A Round Peg in a Ground Hole

題目

題目大意:就是給一些點的座標(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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章