题目链接:http://codeforces.com/gym/101623
题目大意:二维平面内有n个点。现在要你找出两个满足如下条件的正k边形(3<=k<=8)
1、平面内的 n 个点全部在大的正k边形内;
2、小的正k边形嵌套在大的正k边形内,同时没有一个点在小的正k边形内,或者在k边形上;
3、这两个k边形的中心都在原点(0,0);
4、两个正k边形都有一个顶点在x轴的正半轴上。
现在令val = S(小正k边形)/ S(大正k边形)。(S指面积)要你求出最大的val值,同时输出k。
题目思路:由于k的范围很小,所以我们可以考虑直接枚举是几边形进行覆盖,求出所有的val值,最后再取最大值。
对于当前是 k 边形的时候,我们考虑可以用二分正多边形的半径 r (顶点到中心的距离)来求出满足条件时的大小多边形,然后再求出这两个多边形的面积,进行比值即可。
具体实现看代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
const int MX = 1000 + 5;
const double pi = acos(-1.0);
const double eps = 1e-8;
int n;
struct Point {
double x, y;
Point() {}
Point(double x, double y): x(x), y(y) {}
};
Point operator-(Point A, Point B) {return Point(A.x - B.x, A.y - B.y);}
double sqr(double x) {return x * x;}
int dcmp(double x) {
if (fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
double Cross(Point A, Point B) {
return A.x * B.y - A.y * B.x;
}
double Dot(Point A, Point B) {
return A.x * B.x + A.y * B.y;
}
double dist(Point A, Point B) {
return sqrt(sqr(A.x - B.x) + sqr(A.y - B.y));
}
Point Rotate(Point A, double ang) {
return Point(A.x * cos(ang) - A.y * sin(ang), A.x * sin(ang) - A.y * cos(ang));
}
Point p[MX];
bool is_on_Segment(Point A, Point s, Point t) {
return dcmp(Cross(s - A, s - t)) == 0 && dcmp(Dot(s - A, t - A)) <= 0;
}
struct Polygon {
int n;
Point a[MX];
double get_area() {
double sum = 0;
a[n + 1] = a[1];
for (int i = 1; i <= n; ++i) sum += Cross(a[i + 1], a[i]);
return sum / 2;
}
int is_in_polygon(Point pp) {
int num = 0;
a[n + 1] = a[1];
for (int i = 1; i <= n; ++i) {
if (is_on_Segment(pp, a[i], a[i + 1])) return 2;
int s = dcmp(Cross(a[i] - a[i + 1], a[i] - pp));
int s1 = dcmp(a[i].y - pp.y);
int s2 = dcmp(a[i + 1].y - pp.y);
if (s > 0 && s1 <= 0 && s2 > 0) num++;
if (s < 0 && s1 > 0 && s2 <= 0) num--;
}
return num != 0;
}
};
Polygon make_polygon(int n, double r) {
Polygon A;
double ang = pi * 2 / n;
A.n = n;
A.a[1] = Point(r, 0);
for (int i = 2; i <= n; ++i)
A.a[i] = Rotate(A.a[1], pi * 2 - ang * (i - 1));
return A;
}
bool check1(Polygon A) {
for (int i = 1; i <= n; ++i)
if (A.is_in_polygon(p[i]) == 0) return 0;
return 1;
}
bool check2(Polygon A) {
for (int i = 1; i <= n; ++i)
if (A.is_in_polygon(p[i]) == 1) return 0;
return 1;
}
int main() {
//FIN;
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%lf%lf", &p[i].x, &p[i].y);
double ans = 0;
int id = 0;
Polygon A;
for (int i = 3; i <= 8; ++i) {
double l = 0, r = 1e9, out_area = 0, in_area = 0;
while (r - l > eps) {
double mid = (l + r) / 2;
A = make_polygon(i, mid);
if (check1(A)) r = mid;
else l = mid;
}
A = make_polygon(i, l);
out_area = A.get_area();
l = 0 , r = 1e9;
while (r - l > eps) {
double mid = (l + r) / 2;
A = make_polygon(i, mid);
if (check2(A)) l = mid;
else r = mid;
}
A = make_polygon(i, l);
in_area = A.get_area();
double res = in_area / out_area;
if (res > ans) {
ans = res;
id = i;
}
}
printf("%d %.10f\n", id, ans);
return 0;
}