Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Problem J
Cover the Polygon with Your Disk

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.

Input

The input consists of a single test case, formatted as follows. All input items are integers.

$n$ $r$

$x_1$ $y_1$

.

.

.

$x_n$ $y_n$

$n$ is the number of vertices of the polygon ($3 \leq n \leq 10$). $r$ is the radius of the disk ($1 \leq r \leq 100$).
$x_i$ and $y_i$ give the coordinate values of the $i$-th vertex of the polygon ($1 \leq i \leq n$). Coordinate values satisfy $0 \leq x_i \leq 100$ and $0 \leq y_i \leq 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$^{\circ}$. Note that the border of a convex polygon never crosses or touches itself.

Output

Output the largest possible intersection area of the polygon and the disk. The answer should not have an error greater than 0.0001 ($10^{-4}$).

Sample Input 1

4 4
0 0
6 0
6 6
0 6

Sample Output 1

35.759506

Sample Input 2

3 1
0 0
2 1
1 3

Sample Output 2

2.113100

Sample Input 3

3 1
0 0
100 1
99 1

Sample Output 3

0.019798

Sample Input 4

4 1
0 0
100 10
100 12
0 1

Sample Output 4

3.137569

Sample Input 5

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

Sample Output 5

177.728187

Sample Input 6

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

Sample Output 6

7181.603297

Solution in C++14 (judge verdict: Wrong Answer)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <string>
#include <list>

using namespace std;

#define CVector CPoint
typedef long long LL;
typedef unsigned long long ULL;

const LL mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1e-7;
const int INF=0x3f3f3f3f;
inline int readint(){int sum=0;char c=getchar();bool f=0;while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}while(c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}if(f) return -sum;return sum;}
inline LL readLL(){LL sum=0;char c=getchar();bool f=0;while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}while(c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}if(f) return -sum;return sum;}

/*----------------------精度控制--------------------------*/

const double eps=1e-7;
//1:>0 0:=0 -1:<0
int dcmp(double x){
    if(fabs(x)<eps) return 0;
    return x<0?-1:1;
}

/*------------------点、???体-------------------*/

struct Point{
    double x,y;
    Point(double x,double y):x(x),y(y){}
    Point(){}
    void Read(){ scanf("%lf%lf",&x,&y); }
    void Write(){ printf("%.10f %.10f\n",x,y); }
    bool operator<(const Point &b) const{//水平序
        if(!dcmp(x-b.x)) return y<b.y;
        return x<b.x;
    }
    /*friend bool operator<(CPoint a,CPoint b){//?角排序
        double tmp=cross(Pts[0],a,b);
        if(isZero(tmp)){
            return dist(Pts[0],a)<dist(Pts[0],b);
        }
        return tmp>0;
    }*/
};
//a->b
struct Line{
    Point a,b;
    Line(Point a,Point b):a(a),b(b){}
    Line(){}
    void Read(){ a.Read(); b.Read(); }
    void Write(){ a.Write(); b.Write(); }
};

/*---------------------点、?相?----------------------*/
Point operator +(Point a,Point b){ return Point(a.x+b.x,a.y+b.y); }
Point operator -(Point a,Point b){ return Point(a.x-b.x,a.y-b.y); }
Point operator *(Point a,double k){ return Point(k*a.x,k*a.y); }
Point operator *(double k,Point a){ return Point(k*a.x,k*a.y); }
double operator *(Point a,Point b){ return a.x*b.x+a.y*b.y; }
Point operator /(Point a,double k){ return Point(a.x/k,a.y/k); }
double operator ^(Point a,Point b){ return a.x*b.y-a.y*b.x; }

double cross(Point a,Point b){ return a.x*b.y-a.y*b.x; }
//(b-a)^(c-a)
double cross(Point a,Point b,Point c){ return cross(b-a,c-a); }
double dot(Point a,Point b){ return a.x*b.x+a.y*b.y; }
//(b-a)*(c-a)
double dot(Point a,Point b,Point c){ return dot(b-a,c-a); }

double length(Point p){ return sqrt(p*p); }
//?位化
Point unit(Point p){ return 1.0/length(p)*p; }
//求p在n方向上投影?度
double project(Point p,Point n){ return p*unit(n); }
//求a,b所?的有向面?
double area(Point a,Point b){ return a^b*0.5; }

double distPP(Point p,Point q){ return length(p-q); }
double distPL(Point p,Line l){ return fabs((p-l.a)^(p-l.b))/length(l.a-l.b); }
double distPS(Point p,Line s){
    if(dot(s.b-s.a,p-s.a)<0.0) return length(p-s.a);
    if(dot(s.a-s.b,p-s.b)<0.0) return length(p-s.b);
    return distPL(p,s);
}

//b?a逆??旋?alpha后得到的点
Point rotateP(Point a,Point b,double alpha){
    Point p=b-a;
    return Point(a.x+(p.x*cos(alpha)-p.y*sin(alpha)),a.y+(p.x*sin(alpha)+p.y*cos(alpha)));
}

//b?a逆??旋?alpha后得到的向量
Point rotateV(Point a,Point b,double alpha){
    Point p=b-a;
    return unit(Point(p.x*cos(alpha)-p.y*sin(alpha),p.x*sin(alpha)+p.y*cos(alpha)));
}

//0:online 1:left -1:right
int sideOfL(Point p,Line l){
    double res=(p-l.a)^(p-l.b);
    return dcmp(res);
}

//求?p的l的垂?
Line vertical(Point p,Line l){
    return Line(p,p+rotateV(l.b,l.a,PI/2));
}

//垂足
Point root(Point p,Line l){
    return l.a+project(p-l.a,l.b-l.a)*unit(l.b-l.a);
}

//?向量?角
double angleVV(Point a,Point b){ return acos(project(a,b)/length(a)); }
//?直??角
double angleLL(Line l,Line m){
    return acos(fabs(project(l.b-l.a,m.b-m.a)/length(l.b-l.a)));
}

//判断点p是否在?段ab上
bool PointOnS(Point p,Line l){
    return !dcmp(cross(p-l.a,l.b-l.a))&&dcmp((p-l.a)*(p-l.b))<=0;
}

//求直?交点
Point getCrossLL(Line l,Line m){
    double t=cross(m.b-m.a,l.a-m.a)/cross(l.b-l.a,m.b-m.a);
    return l.a+(l.b-l.a)*t;
}

//判断?段是否相交
bool crossSS(Line l,Line m){
    return sideOfL(l.a,m)*sideOfL(l.b,m)<=0&&sideOfL(m.a,l)*sideOfL(m.b,l)<=0;
}

/*----------------------多?形相?--------------------------*/

//0:outside 1:inside 2:online
int PointInPoly(Point t,Point *Pts,int n){
    int num=0,d1,d2,k;
    Pts[n]=Pts[0];
    for(int i=0;i<n;i++){
        if(PointOnS(t,Line(Pts[i],Pts[i+1]))) return 2;
        k=dcmp(cross(Pts[i],Pts[i+1],t));
        d1=dcmp(Pts[i].y-t.y);
        d2=dcmp(Pts[i+1].y-t.y);
        if(k>0&&d1<=0&&d2>0) num++;
        if(k<0&&d2<=0&&d1>0) num--;
    }
    return num!=0;
}

//clockwise:>0 anticlockwise:<0
double PolyArea(Point *Pts,int n){
    double pa=area(Pts[n-1],Pts[0]);
    for(int i=0;i<n-1;i++) pa+=area(Pts[i],Pts[i+1]);
    return pa;
}

//求任意多?形周?，需逆??或???排列
double PolyPerimeter(Point *Pts,int n){
    double pp=distPP(Pts[n-1],Pts[0]);
    for(int i=0;i<n-1;i++) pp+=distPP(Pts[i],Pts[i+1]);
    return pp;
}

//求多?形重心坐?
Point PolyCore(Point *Pts,int n){
    double pa=PolyArea(Pts,n);
    if(!dcmp(pa)) return Point(0,0);
    Point ans=(Pts[n-1]+Pts[0])*cross(Pts[n-1],Pts[0]);
    for(int i=0;i<n-1;i++) ans=ans+(Pts[i]+Pts[i+1])*cross(Pts[i],Pts[i+1]);
    return ans/pa/6;
}

/*----------------------凸包----------------------------*/

//Graham-scan st:anticlockwise
//<=:strict <:Non-strict
int Graham(Point *Pts,Point *st,int n){
    if(n<3) return 0;
    sort(Pts,Pts+n);
    int m=0;
    for(int i=0;i<n;i++){
        while(m>1&&dcmp(cross(st[m-2],st[m-1],Pts[i]))<0) m--;
        st[m++]=Pts[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--){
        while(m>k&&dcmp(cross(st[m-2],st[m-1],Pts[i])<0)) m--;
        st[m++]=Pts[i];
    }
    return m-1;
}

//clockwise:> anticlockwise:<
double CHDiameter(Point *Pts,int n,Line &l){
    double maxd=0.0;
    if(n<=1){
        l.a=l.b=Pts[0];
        return maxd;
    }
    for(int i=0,j=1;i<n;i++){
        while(cross(Pts[i],Pts[(i+1)%n],Pts[j])
              >cross(Pts[i],Pts[(i+1)%n],Pts[(j+1)%n])){
            j=(j+1)%n;
        }
        double d=distPP(Pts[i],Pts[j]);
        if(dcmp(d-maxd)>=0){
            maxd=d;
            l.a=Pts[i];
            l.b=Pts[j];
        }
        d=distPP(Pts[(i+1)%n],Pts[(j+1)%n]);
        if(dcmp(d-maxd)>=0){
            maxd=d;
            l.a=Pts[i];
            l.b=Pts[j];
        }
    }
    return maxd;
}

/*---------------------整点多?形---------------------------*/

int gcd(int a,int b){
    return b==0?a :gcd(b,a%b);
}

//整点多?形?界整点数
int Border_Int_Point_Num(Point *Pts,int n){
    int num=gcd(abs(int(Pts[0].x-Pts[n-1].x)),abs(int(Pts[0].y-Pts[n-1].y)));;
    for(int i=0;i<n-1;i++){
        num+=gcd(abs(int(Pts[i+1].x-Pts[i].x)),abs(int(Pts[i+1].y-Pts[i].y)));
    }
    return num;
}

//整点多?形内部整点数
int Inside_Int_Point_Num(Point *Pts,int n){
    return abs(int(PolyArea(Pts,n)))+1-Border_Int_Point_Num(Pts,n)/2;
}

/*-----------------------------半平面交-------------------------------*/

//有方向的直?
//p->p+v
struct Vector{
    Point p,v;
    double ang;
    Vector(Point p,Point v):p(p),v(v){
        ang=atan2(v.y,v.x);
    }
    Vector(){}
    bool operator<(const Vector &l) const{
        return ang<l.ang;
    }
};

//判断点p是否在直?L左?
bool onLeft(Vector L,Point p){
    return cross(L.v,p-L.p)>0;
}

//得到a与b?直?的交点
Point getCrossVV(Vector a,Vector b){
    Point u=a.p-b.p;
    double t=cross(b.v,u)/cross(a.v,b.v);
    return a.p+a.v*t;
}

//所有直?左半平面的交
int HPCross(Vector *L,int n,Point *poly){
    sort(L,L+n);
    int f=0,l=0;
    Point *p=new Point[n];
    Vector *q=new Vector[n];
    q[0]=L[0];
    for(int i=1;i<n;i++){
        while(f<l&&!onLeft(L[i],p[l-1])) l--;
        while(f<l&&!onLeft(L[i],p[f])) f++;
        q[++l]=L[i];
        if(!dcmp(cross(q[l].v,q[l-1].v))){
            l--;
            if(onLeft(q[l],L[i].p)) q[l]=L[i];
        }
        if(f<l) p[l-1]=getCrossVV(q[l-1],q[l]);
    }
    while(f<l&&!onLeft(q[f],p[l-1])) l--;
    if(l-f<=1) return 0;
    p[l]=getCrossVV(q[l],q[f]);
    int m=0;
    for(int i=f;i<=l;i++) poly[m++]=p[i];
    return m;
}

#define maxn 100005
Vector l[maxn];
bool retract(Vector *L,int n,double r,Point *poly){
    for(int i=0;i<n;i++){
        Point v=rotateV(L[i].p,L[i].p+L[i].v,PI/2);
        l[i]=Vector(L[i].p+r*v,L[i].v);
    }
    int cnt=HPCross(l,n,poly);
    return cnt;
}

/*---------------------三角形相?---------------------------*/

//三角形重心
//到三?点距?的平方和最小的点
//到三?距?之?最大的点
Point TCore(Point a,Point b,Point c){
    return (a+b+c)/3;
}

//三角形外心
Point TCircum(Point a,Point b,Point c){
    Point cp;
    double a1=b.x-a.x;
    double b1=b.y-a.y;
    double a2=c.x-a.x;
    double b2=c.y-a.y;
    double c1=(a1*a1+b1*b1)/2;
    double c2=(a2*a2+b2*b2)/2;
    double d=a1*b2-a2*b1;
    cp.x=a.x+(c1*b2-c2*b1)/d;
    cp.y=a.y+(a1*c2-a2*c1)/d;
    return cp;
}

//三角形垂心
Point TOrtho(Point a,Point b,Point c){
    return TCore(a,b,c)*3.0-TCircum(a,b,c)*2.0;
}

//三角形内心
Point TInner(Point a,Point b,Point c){
    Point cp;
    double la=distPP(b,c),lb=distPP(c,a),lc=distPP(a,b);
    cp.x=(la*a.x+lb*b.x+lc*c.x)/(la+lb+lc);
    cp.y=(la*a.y+lb*b.y+lc*c.y)/(la+lb+lc);
    return cp;
}

//求三角形面?
double TArea(Point a,Point b,Point c){
    return fabs(cross(a,b,c))/2;
}

/*-----------------------?相?-------------------------*/

struct Circle{
    Point o; double r;
    Circle(Point o,double r):o(o),r(r){}
    Circle(){}
    void Read(){ o.Read(); scanf("%lf",&r); }
    double area(){ return PI*r*r; }
};

//求??面?交
double getAreaCC(Circle a,Circle b){
    double d=(a.o.x-b.o.x)*(a.o.x-b.o.x)+(a.o.y-b.o.y)*(a.o.y-b.o.y);
    if(d<=(a.r-b.r)*(a.r-b.r)){
        return min(a.r,b.r)*min(a.r,b.r)*PI;
    }else if(d>(a.r-b.r)*(a.r-b.r)&&d<(a.r+b.r)*(a.r+b.r)){
        double m1=(a.r*a.r+d-b.r*b.r)/(2*a.r*sqrt(d));
        double m2=(b.r*b.r+d-a.r*a.r)/(2*b.r*sqrt(d));
        double s1=acos(m1)*a.r*a.r;
        double s2=acos(m2)*b.r*b.r;
        double s3=sqrt(d)*a.r*sin(acos(m1));
        return s1+s2-s3;
    }
    return 0.0;
}

int getCrossCL(Circle c,Line l,Point *cl){
    int fg=dcmp(distPL(c.o,l)-c.r);
    int cnt=0;
    if(!fg){
        cl[cnt++]=root(c.o,l);
    }else if(fg==-1){
        Point rt=root(c.o,l);
        double r=sqrt(c.r*c.r-(c.o-rt)*(c.o-rt));
        cl[cnt++]=rt+r*unit(l.b-l.a);
        cl[cnt++]=rt-r*unit(l.b-l.a);
    }
    return cnt;
}
/********************************************************/
int getCrossCS(Circle c,Line s,Point *cs){
    Point tmp[2];
    int cnt=0;
    int ct=getCrossCL(c,s,tmp);
    for(int i=0;i<ct;i++){
        if(PointOnS(tmp[i],s)) cs[cnt++]=tmp[i];
    }
    return cnt;
}

Point PinS(Point *cs,int n,Line s){
    if(n==1) return cs[0];
    if(!dcmp(cs[0].x-s.a.x)&&!dcmp(cs[0].y-s.a.y)) return cs[1];
    return cs[0];
}

double getAngle(Point a,Point b){
    double tmp=unit(a)*unit(b);
    if(tmp<-1.0) tmp=-1.0;
    if(1.0<tmp) tmp=1.0;
    return acos(tmp);
}

double getAreaTC(Point a,Point b,Circle c){
    double atc=fabs(cross(a-c.o,b-c.o)/2);
    if(!dcmp(atc)) return 0.0;
    double la=length(a-c.o),lb=length(b-c.o);
    Point cs[4];
    if(la<c.r+EPS&&lb>c.r-EPS){
        int ct=getCrossCS(c,Line(a,b),cs);
        Point p=PinS(cs,ct,Line(a,b));
        atc+=c.r*c.r*getAngle(p-c.o,b-c.o)/2;
        atc-=fabs(cross(p-c.o,b-c.o)/2);
    }else if(la>c.r-EPS&&lb<c.r+EPS){
        int ct=getCrossCS(c,Line(a,b),cs);
        Point p=PinS(cs,ct,Line(b,a));
        atc+=c.r*c.r*getAngle(p-c.o,a-c.o)/2;
        atc-=fabs(cross(p-c.o,a-c.o)/2);
    }else if(la>c.r-EPS&&lb>c.r-EPS){
        if(distPS(c.o,Line(a,b))<c.r-EPS){
            Point rt=root(c.o,Line(a,b));
            atc=fabs(getAreaTC(a,rt,c))+fabs(getAreaTC(rt,b,c));
        }else atc=c.r*c.r*getAngle(a-c.o,b-c.o)/2;
    }
    if(dcmp(cross(a-c.o,b-c.o))==1) atc=-atc;
    return atc;
}

double getAreaPC(Point *Pts,int n,Circle c){
    double apc=getAreaTC(Pts[n-1],Pts[0],c);
    for(int i=0;i<n-1;i++) apc+=getAreaTC(Pts[i],Pts[i+1],c);
    return fabs(apc);
}

/********************************************************/


/*----------------------三?点、?基本函数-----------------------------*/

struct Point3{
    double x,y,z;
    Point3(double x,double y,double z):x(x),y(y),z(z){}
    Point3(){}
    void Read(){ scanf("%lf%lf%lf",&x,&y,&z); }
};

struct Line3{
    Point3 a,b;
    Line3(Point3 a,Point3 b):a(a),b(b){}
    Line3(){}
    void Read(){ a.Read(); b.Read(); }
};
Point3 operator +(Point3 a,Point3 b){ return Point3(a.x+b.x,a.y+b.y,a.z+b.z); }
Point3 operator -(Point3 a,Point3 b){ return Point3(a.x-b.x,a.y-b.y,a.z-b.z); }
double operator *(Point3 a,Point3 b){ return a.x*b.x+a.y*b.y+a.z*b.z; }
Point3 operator *(Point3 a,double k){ return Point3(a.x*k,a.y*k,a.z*k); }
Point3 operator *(double k,Point3 a){ return Point3(a.x*k,a.y*k,a.z*k); }
Point3 operator /(Point3 a,double k){ return Point3(a.x/k,a.y/k,a.z/k); }

double length(Point3 a){ return sqrt(a.x*a.x+a.y*a.y+a.z*a.z); }
Point3 unit(Point3 a){ return a/length(a); }
double dot(Point3 a,Point3 b){ return a.x*b.x+a.y*b.y+a.z*b.z; }
Point3 cross(Point3 a,Point3 b){
    return Point3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
//混合?
double Mix(Point3 a,Point3 b,Point3 c){
    return dot(a,cross(b,c));
}

//?点距?
double dist(const Point3 &a,const Point3 &b){ return length(a-b); }

/*---------------------------------体?-------------------------------------*/

//四面体体?
double volume(double l,double n,double a,double m,double b,double c){
    double x,y;
    x=4*a*a*b*b*c*c-a*a*(b*b+c*c-m*m)*(b*b+c*c-m*m)-b*b*(c*c+a*a-n*n)*(c*c+a*a-n*n);
    y=c*c*(a*a+b*b-l*l)*(a*a+b*b-l*l)-(a*a+b*b-l*l)*(b*b+c*c-m*m)*(c*c+a*a-n*n);
    return sqrt(x-y)/12;
}

double volume(Point3 a,Point3 b,Point3 c,Point3 d){
    return fabs(Mix(b-a,c-a,d-a)/6);
}

#define MAXN 15
Point Pts[MAXN];
int n;
double R,minx,miny,maxx,maxy;

double sanfeny(double x){
    double l=miny,r=maxy;
    double m1,m2;
    for(int i=0;i<100;i++){
        m1=(l+l+r)/3;
        m2=(l+r+r)/3;
        if(getAreaPC(Pts,n,Circle(Point(x,m1),R))<getAreaPC(Pts,n,Circle(Point(x,m2),R))){
            l=m1;
        }else{
            r=m2;
        }
    }
    return getAreaPC(Pts,n,Circle(Point(x,l),R));
}

double sanfenx(){
    double l=minx,r=maxx;
    double m1,m2;
    for(int i=0;i<100;i++){
        m1=(l+l+r)/3;
        m2=(l+r+r)/3;
        if(sanfeny(m1)<sanfeny(m2)){
            l=m1;
        }else{
            r=m2;
        }
    }
    return sanfeny(l);
}

int main(){ios_base::sync_with_stdio(0);//cin.tie(0);
    minx=miny=1000;
    maxx=maxy=0;
    cin>>n>>R;
    for(int i=1;i<=n;i++){
        cin>>Pts[n-i].x>>Pts[n-i].y;
        minx=min(minx,Pts[n-i].x);
        miny=min(miny,Pts[n-i].y);
        maxx=max(maxx,Pts[n-i].x);
        maxy=max(maxy,Pts[n-i].y);
    }
    Pts[n]=Pts[0];
    double maans=sanfenx();
    cout.setf(ios::fixed);
    cout<<fixed<<setprecision(10)<<maans<<endl;
    return 0;
}

//cout.setf(ios::fixed);
//cout<<fixed<<setprecision(10)<<s<<endl;