列表

详情


NC207728. CoverthePolygonwithYourDisk

描述

A convex polygon is drawn on a flat paper sheet. You are trying to place a disk in your hands to cover as large area of the polygon as possible. In other words, the intersection area of the polygon and the disk should be maximized.

输入描述

The input consists of a single test case, formatted as follows. All input items are integers. 
n r 
x1 y
... 
xn yn 
n is the number of vertices of the polygon (3 ≤ n ≤ 10). r is the radius of the disk (1 ≤ r ≤ 100).xi and yi give the coordinate values of the i-th vertex of the polygon (1 ≤ i ≤ n). Coordinatevalues satisfy 0 ≤ xi ≤ 100 and 0 ≤ yi ≤ 100.The vertices are given in counterclockwise order. As stated above, the given polygon is convex.In other words, interior angles at all of its vertices are less than 180◦. Note that the border ofa convex polygon never crosses or touches itself.

输出描述

Output the largest possible intersection area of the polygon and the disk. The answer shouldnot have an error greater than 0.0001 (10−4 ).

示例1

输入:

4 4
0 0
6 0
6 6
0 6

输出:

35.759506

示例2

输入:

3 1
0 0
2 1
1 3

输出:

2.113100

示例3

输入:

3 1
0 0
100 1
99 1

输出:

0.019798

示例4

输入:

4 1
0 0
100 10
100 12
0 1

输出:

3.137569

示例5

输入:

10 10
0 0
10 0
20 1
30 3
40 6
50 10
60 15
70 21
80 28
90 36

输出:

177.728187

示例6

输入:

10 49
50 0
79 10
96 32
96 68
79 90
50 100
21 90
4 68
4 32
21 10

输出:

7181.603297

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: <1ms, 内存消耗: 0K, 提交时间: 2023-08-18 22:53:24

#include<bits/stdc++.h>
#define inf 1000000000000
#define M 100009
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;
struct node
{
    double x,y;
    node(){}
    node(double xx,double yy)
    {
        x=xx;
        y=yy;
    }
    node operator -(node s)
    {
        return node(x-s.x,y-s.y);
    }
    node operator +(node s)
    {
        return node(x+s.x,y+s.y);
    }
    double operator *(node s)
    {
        return x*s.x+y*s.y;
    }
    double operator ^(node s)
    {
        return x*s.y-y*s.x;
    }
}p[M],a[M];
double max(double a,double b)
{
    return a>b?a:b;
}
double min(double a,double b)
{
    return a<b?a:b;
}
double len(node a)
{
    return sqrt(a*a);
}
double dis(node a,node b)//两点之间的距离
{
    return len(b-a);
}
double cross(node a,node b,node c)//叉乘
{
    return (b-a)^(c-a);
}
double dot(node a,node b,node c)//点乘
{
    return (b-a)*(c-a);
}
int judge(node a,node b,node c)//判断c是否在ab线段上(前提是c在直线ab上)
{
    if(c.x>=min(a.x,b.x)
       &&c.x<=max(a.x,b.x)
       &&c.y>=min(a.y,b.y)
       &&c.y<=max(a.y,b.y))
        return 1;
    return 0;
}
double area(node b,node c,double r)
{
    node a(0.0,0.0);
    if (dis(b,c)<eps) return 0.0;
    double h=fabs(cross(a,b,c))/dis(b,c);
    if(dis(a,b)>r-eps&&dis(a,c)>r-eps)//两个端点都在圆的外面则分为两种情况
    {
        double angle=acos(dot(a,b,c)/dis(a,b)/dis(a,c));
        if(h>r-eps)
        {
            return 0.5*r*r*angle;
        }
        else if(dot(b,a,c)>0&&dot(c,a,b)>0)
        {
            double angle1=2*acos(h/r);
            return 0.5*r*r*fabs(angle-angle1)+0.5*r*r*sin(angle1);
        }
        else
        {
            return 0.5*r*r*angle;
        }
    }
    else if(dis(a,b)<r+eps&&dis(a,c)<r+eps)//两个端点都在圆内的情况
    {
        return 0.5*fabs(cross(a,b,c));
    }
    else//一个端点在圆上一个端点在圆内的情况
    {
        if(dis(a,b)>dis(a,c))//默认b在圆内
        {
            swap(b,c);
        }
        if(fabs(dis(a,b))<eps)//ab距离为0直接返回0
        {
            return 0.0;
        }
        if(dot(b,a,c)<eps)
        {
            double angle1=acos(h/dis(a,b));
            double angle2=acos(h/r)-angle1;
            double angle3=acos(h/dis(a,c))-acos(h/r);
            return 0.5*dis(a,b)*r*sin(angle2)+0.5*r*r*angle3;

        }
        else
        {
            double angle1=acos(h/dis(a,b));
            double angle2=acos(h/r);
            double angle3=acos(h/dis(a,c))-angle2;
            return 0.5*r*dis(a,b)*sin(angle1+angle2)+0.5*r*r*angle3;
        }
    }
}
int n;
double x,y,h,x1,yy,R;
double gets(node O)//求圆与多边形面积并
{
    for (int i=1;i<=n+1;i++) p[i]=a[i];
      for(int i=1;i<=n+1;i++) p[i]=p[i]-O;
    O=node(0,0);
    double sum=0;
    for(int i=1;i<=n;i++)
    {
        int j=i+1;
        double s=area(p[i],p[j],R);
        if(cross(O,p[i],p[j])>0) sum+=s; else sum-=s;
    }
    return fabs(sum);
}
int dcmp(double x)
{
    if(x > eps) return 1;
    return x < -eps ? -1 : 0;
}
double calc(double x)
{
    double l=1000000,r=-100000,m1,m2,f1=0,f2=0;
    for (int i=1;i<=n;i++)
    {
        if (dcmp((a[i].x-x) * (a[i+1].x-x))<=0)
        {
            node tmp;
            tmp.x=a[i].x+(a[i+1].x-a[i].x)/(a[i+1].x-a[i].x)*(x-a[i].x);
            tmp.y=a[i].y+(a[i+1].y-a[i].y)/(a[i+1].x-a[i].x)*(x-a[i].x);
            l=min(l,tmp.y);
            r=max(r,tmp.y);
        }
    }
    while (l+eps<r)
    {
        m1=(l+l+r)/3.0;
        node bom=node(x,m1);
        f1=gets(bom);
        m2=(l+r+r)/3.0;
        bom=node(x,m2);
        f2=gets(bom);
        if (f1>f2) r=m2;else l=m1;
    }
    return f1;
}
int main()
{
    scanf("%d%lf",&n,&R);
    double l=1000,r=-1000,m1,m2,f1,f2;
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&a[i].x,&a[i].y);
        l=min(l,a[i].x);
        r=max(r,a[i].x);
    }
    a[n+1]=a[1];
    while (l+eps<r)
    {
        m1=(l+l+r)/3.0;f1=calc(m1);
        m2=(l+r+r)/3.0;f2=calc(m2);
        if (f1>f2) r=m2;else l=m1;
    }
    printf("%.6lf\n",f1);
    return 0;
}

上一题