题意:有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;
}