2017-2018 Northwestern European Regional Contest (NWERC 2017) G Glyph Recognition

版权声明:转载请注明出处 https://blog.csdn.net/jay__bryant/article/details/82120656

题意:有6种正多边形(边数为3~8)。给出n个点,求选择哪种正多边形(中心在原点,在x正半轴有一个点),n个点全部在in多边形的外部,全部在out多边形的内部,使得area(in)/area(out)最大。

枚举多边形的种类,二分半径更新答案
平面几何,版子多才是王道

#include <cstdio>
#include <cmath>

using namespace std;
const double eps = 1e-8;
const int N = 1010;
const int mod = 1e9+7;
const double PI = acos(-1.0);
const double upr = 1e9;
int sgn(double x) {return fabs(x)<eps?0:(x<0?-1:1);}
struct point
{
    double x, y;
    point(){}
    point(double _x, double _y):x(_x),y(_y){}
    point operator -(const point &p)const
    {
        return point(p.x-x, p.y-y);
    }
    double cross(const point &p)const
    {
        return x*p.y-y*p.x;
    }
    double dot(const point &p)const
    {
        return x*p.x+y*p.y;
    }
    double dist(const point &p)const
    {
        return sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y));
    }
    point rotate_point(const double &a)const
    {
        return point(x*cos(a)-y*sin(a), x*sin(a)+y*cos(a));
    }
};
point p[N];
bool PointonSegment(point p, point s, point t)
{//判断点p是否在线段st上
    return sgn((s-p).cross(s-t))==0 && sgn((s-p).dot(t-p))<=0;
}
struct polygon
{
    int n;
    point a[N];
    double area()//面积求法
    {
        double sum = 0;
        a[n+1] = a[1];
        for(int i = 1; i <= n; ++i) sum += a[i+1].cross(a[i]);
        return sum/2;
    }
    int point_in(point p)//点在多边形内部判断
    {
        int num = 0;
        a[n+1] = a[1];
        for(int i = 1; i <= n; ++i)
        {
            if(PointonSegment(p, a[i], a[i+1])) return 2;
            int s = sgn((a[i]-a[i+1]).cross(a[i]-p));
            int s1 = sgn(a[i].y-p.y);
            int s2 = sgn(a[i+1].y-p.y);
            if(s>0 && s1<=0 && s2>0) ++num;
            if(s<0 && s1>0 && s2<=0) --num;
        }
        return num!=0;
    }
}po;
int n;
void makePo(int n, double r)
{
    double ang = PI*2.0/n;
    po.a[1] = point(r, 0);//(r, 0)处必有一个点
    for(int i = 2; i <= n; ++i)
        po.a[i] = po.a[1].rotate_point(PI*2-ang*(i-1));
}
bool checkin()
{
    for(int i = 1; i <= n; ++i)
        if(po.point_in(p[i])==0) return 0;
    return 1;
}
bool checkout()
{
    for(int i = 1; i <= n; ++i)
        if(po.point_in(p[i])==1) return 0;
    return 1;
}
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
        scanf("%lf %lf", &p[i].x, &p[i].y);
    double ans = 0.0;
    int shape;
    for(int i = 3; i <= 8; ++i)
    {
        po.n = i;
        double l = 0.0, r = upr;
        while(r-l>eps)
        {
            double mid = (l+r)/2;
            makePo(i, mid);
            if(checkin()) r = mid;
            else l = mid;
        }
        double out = po.area();
        l = 0.0;
        r = upr;
        while(r-l>eps)
        {
            double mid = (l+r)/2;
            makePo(i, mid);
            if(checkout()) l = mid;
            else r = mid;
        }
        double in = po.area();
        double tmp = in/out;
        if(tmp > ans)
        {
            ans = tmp;
            shape = i;
        }
    }
    printf("%d %.10f\n", shape, ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/82120656