POJ 1584 A Round Peg in a Ground Hole

先判断是不是N多边形,求一下凸包,如果所有点都用上了,那么就是凸多边形

判断圆是否在多边形内,

先排除圆心在多边形外的情况

剩下的情况可以利用圆心到每条边的最短距离与半径的大小来判断

#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<list>
#include<algorithm>
using namespace std;

const double eps=1e-8;
const double pi=2*asin(1.0);
struct point
{
    double x,y;
    double alpha;
    double len2;
    int id;
} p[200];
int T,n;
vector<point>v;
vector<int>ans;

double MinY;
int MinId;

bool cmp(const point &a, const point &b)
{
    if(fabs(a.alpha-b.alpha)<eps) return a.len2<b.len2;
    return a.alpha<b.alpha;
}

double len2(point a,point b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

double f(point a,point b,point c) //返回点a所对应的角的弧度
{
    double B2=(double)len2(a,c);
    double C2=(double)len2(a,b);
    double A2=(double)len2(b,c);
    double COSA=(B2+C2-A2)/(2*sqrt(B2)*sqrt(C2));
    return pi-acos(COSA);
}

double GetPointDistance(point p1, point p2)
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

double GetNearestDistance(point PA, point PB, point P3)
{
    double a,b,c;
    a=GetPointDistance(PB,P3);
    if(a<=0.00001) return 0.0f;
    b=GetPointDistance(PA,P3);
    if(b<=0.00001) return 0.0f;
    c=GetPointDistance(PA,PB);
    if(c<=0.00001) return a;
    if(a*a>=b*b+c*c) return b;
    if(b*b>=a*a+c*c) return a;
    double l=(a+b+c)/2;
    double s=sqrt(l*(l-a)*(l-b)*(l-c));
    return 2*s/c;
}

bool check(point T)
{
    double sum=0;
    for(int i=0;i<ans.size();i++)
        sum=sum+pi-(f(T,p[ans[i]],p[ans[(i+1)%ans.size()]]));
    if(fabs(sum-2*pi)<eps) return 0;
    return 1;
}

int main()
{
    double pegRadius ,pegX ,pegY ;
    while(~scanf("%d", &n))
    {
        if(n<3) break;
        scanf("%lf%lf%lf",&pegRadius,&pegX,&pegY);
        MinY=9999999999999;
        for(int i=1; i<=n; i++)
        {
            scanf("%lf%lf", &p[i].x, &p[i].y);
            p[i].id=i;
            if(p[i].y<MinY)
            {
                MinY=p[i].y;
                MinId=i;
            }
        }

        ans.clear();

        point pre; pre.x=-9999999999999; pre.y=p[MinId].y;
        point now; now.x=p[MinId].x; now.y=p[MinId].y; now.id=MinId;

        for(int i=1; i<=n; i++)
        {
            v.clear();
            for(int k=1; k<=n; k++)
            {
                if(p[k].id!=now.id)
                {
                    p[k].alpha=f(now,p[k],pre);
                    p[k].len2=len2(p[k],now);
                    v.push_back(p[k]);
                }
            }
            sort(v.begin(),v.end(),cmp);
            ans.push_back(v[0].id);
            if(v[0].id==MinId) break;

            pre.x=now.x;
            pre.y=now.y;
            pre.id=now.id;
            now.x=v[0].x;
            now.y=v[0].y;
            now.id=v[0].id;
        }

        if(ans.size()<n) printf("HOLE IS ILL-FORMED\n");

        else
        {
            bool fail=0;
            point T;
            T.x=pegX;
            T.y=pegY;

            if(check(T)) {fail=1;}
            else
            {
                for(int i=0; i<ans.size(); i++)
                {
                    double len=GetNearestDistance(p[ans[i]],p[ans[(i+1)%ans.size()]],T);
                    if(len+eps<=pegRadius) fail=1;
                }
            }

            if(fail==0) printf("PEG WILL FIT\n");
            else printf("PEG WILL NOT FIT\n");
        }
    }
    return 0;
}

 

posted @ 2016-01-24 21:00  Fighting_Heart  阅读(157)  评论(0编辑  收藏  举报