poj 1584 A Round Peg in a Ground Hole

来源:互联网 发布:php支付接口demo 编辑:程序博客网 时间:2024/05/21 09:15
题意:1.所有的点不能刚好能构成凸包输出:HOLE IS ILL-FORMED
      2.否则如果圆不超出凸包输出:PEG WILL FIT,不然输出:PEG WILL NOT FIT

分析:先判断判断是不是凸包, 是凸包的情况下判断圆是否在凸包内(包括内切)。


判断凸包:获取凸包,如果最后顶点数和凸包顶点数不一样就不是。


判断圆是否在凸包内:判断圆心在凸包内,在则获取圆心到凸包边上的最小值。大于半径则不在。


判断圆心和凸包的关系:1.查看有向面积符号的一致性O(n)。2.二分极角判断O(log(n))。

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<string>#include <map>#include <vector>#include<algorithm>#include <complex>#define eps 1e-8#define INF 1e8using namespace std;typedef double TYPE;inline int sgn(double x){return x < -eps ? -1 : ( x > eps? 1 :  0);}struct Point{    TYPE x, y;    Point(){}    Point(const TYPE &xx, const TYPE &yy):x(xx), y(yy){}    void input(){scanf("%lf %lf", &x, &y);}    void output(){ printf("%.2f %.2f\n", x, y);}    Point operator + (const Point &p)const{ return Point(x + p.x, y + p.y);}    Point operator - (const Point &p)const{return Point(x- p.x, y - p.y);}    Point operator / (const TYPE &w)const{return Point(x /w, y/w );}    Point operator * (const TYPE &w)const{ return Point(x * w, y * w);}    friend Point operator * (const TYPE &w, const Point &p){ return Point(w * p.x, w * p.y);}    bool operator < (const Point &p)const{ return x < p.x || ( x == p.x && y < p.y);}    friend double det(const Point &a, const Point &b){ return a.x* b.y - a.y * b.x;}    friend double dot(const Point &a, const Point &b){return a.x * b.x + a.y* b.y;}    double norm()const{ return sqrt(x * x + y * y);}};struct Line{    Point s, t;    Line(){}    Line(Point ss, Point tt):s(ss), t(tt){}    double distPointToLine(const Point &p){        if(sgn(dot(t - s, p - s)) < 0)return (p - s).norm();        if(sgn(dot( s - t, p - t)) < 0)return (p - t).norm();        return (fabs(det(s - p, t - p))/ (s - t).norm());    }};struct Hull{    int n;    vector<Point>v;    Hull( ){        v.resize(0);    }    void getHull(vector<Point> &ps){        int tSize = ps.size();        v.resize(0);        sort(ps.begin(), ps.end());        int m = 0;        for(int i = 0; i < tSize; i++){            while(m > 1 && sgn(det(v[m - 1] - v[m - 2], ps[i] - v[m - 2])) < 0)m--, v.pop_back();            v.push_back(ps[i]);            m++;        }        int k = m;        for(int i = tSize - 2; i >= 0; i--){            while(m > k && sgn(det(v[m - 1] - v[m - 2], ps[i] - v[m - 2])) < 0 )m--, v.pop_back();            v.push_back(ps[i]);            m++;        }        v.resize(m);        if(m > 0)v.resize(m - 1);//        for(int i = 0;i  < v.size();i ++){//            v[i].output();//        }    }   bool isContain(const Point &t){      //  16MS过~        int sign  = 0;        int tSize = v.size();        for(int i = 0; i < tSize; i++){            if(sgn(det(t - v[i], t - v[(i + 1)%tSize])) == 0){ return true;}//边界上        }        for(int i = 0; i < tSize; i++){            int tSign = sgn(det(v[(i + 1)%tSize] - t, v[i] - t));            if(tSign){                if(sign){                    if(sign != tSign)return false;//外面                }else {                    sign = tSign;                }            }        }        return true;//内部   }   //二分极角,Olog(n)版本判断点和凸包的位置关系, 0MS过,神奇!   bool isContainOlogn(Point &t){        int n =  v.size(), l = 0, r = n;        Point g = (v[0] + v[n / 3] + v[n * 2/ 3])/3.0;//凸包内部一个点(其中一个三角形的重心);        while(l + 1< r){            int mid = (r + l)>> 1;            int k = sgn(det(v[l] - g, v[mid] - g));            int res1 = sgn(det(v[l] - g, t - g));            int res2 = sgn(det(v[mid] - g, t - g));            if(k > 0){                 if(res1>= 0 && res2< 0){                    r = mid;                 }else {                    l = mid;                 }            }else {                if(res1 < 0 &&res2 >=0 ){                    l = mid;                }else {                    r = mid;                }            }        }        r %= n;        int res = sgn(det(v[r] - t, v[l] - t));        if(res == -1 || res == 0)return true;        return false;   }}hull;vector<Point>ps;Point co;double r;int n;void init(){        scanf("%lf", &r);        co.input();        ps.resize(n);        for(int i = 0; i < n; i++){            ps[i].input();        }}void solve(){    hull.getHull(ps);    if(ps.size() != hull.v.size()){        puts("HOLE IS ILL-FORMED");    }else {        if(hull.isContainOlogn(co)){            int tSize = hull.v.size();            double min_d = INF;            for(int i = 0;i < tSize; i++){                Line line(hull.v[i], hull.v[(i+1)%tSize]);                min_d = min(line.distPointToLine(co), min_d);            }            if(sgn(min_d - r) >= 0){                puts("PEG WILL FIT");            }else {                puts("PEG WILL NOT FIT");            }        }else {            puts("PEG WILL NOT FIT");        }    }}int main(){    while(scanf("%d", &n), n > 2){        init();        solve();    }    return 0 ;}



原创粉丝点击