#include <cassert>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define printf(...) /*qt rocks*/;
enum { maxpoints = 100001 };
int points;
int point[maxpoints][2];
int sorted[maxpoints];
inline bool equal(double, double);
struct Point
{
double ang, dist;
int id;
/**
* Smaller by angle or, if equal angle, smaller by dist
*/
bool operator<(const Point &p) const
{
if(equal(ang, p.ang))
return dist < p.dist;
else
return ang < p.ang;
}
} polar_point[maxpoints];
int base; //point with lowest x (and lowest y if tie)
int nhull;
int hull[maxpoints];
double ans;
inline double square(double val)
{
return val * val;
}
inline double dist_squared(const double a[2], const double b[2])
{
return square(a[0] - b[0]) + square(a[1] - b[1]);
}
inline double dist(int a, int b)
{
assert(a >= 0 && a < points);
assert(b >= 0 && b < points);
double pa[2] = { point[a][0], point[a][1] },
pb[2] = { point[b][0], point[b][1] };
return sqrt( dist_squared(pa, pb) );
}
inline double dist(int p, const double a[2])
{
double pp[2] = { point[p][0], point[p][1] };
return sqrt( dist_squared(pp, a) );
}
inline bool equal(double a, double b)
{
static const double eps = 1e-7;
return fabs(a - b) < eps;
}
inline double cross(const double v[2], const double w[2])
{
printf("cross %lf,%lf %lf,%lf %lf\n", v[0], v[1], w[0], w[1], v[0] * w[1] - v[1] * w[0]);
return v[0] * w[1] - v[1] * w[0];
}
inline double dot(const double v[2], const double w[2])
{
return v[0] * w[0] + v[1] * w[1];
}
inline bool leftof(int a, int b, int p)
{
double v[2] = { point[b][0] - point[a][0], point[b][1] - point[a][1] },
w[2] = { point[p][0] - point[a][0], point[p][1] - point[a][1] };
return cross(v, w) > 0;
}
inline bool leftof(int p, const double l[2][2])
{
//a, b, p -- l[0], l[1], p
double v[2] = { l[1][0] - l[0][0], l[1][1] - l[0][1] },
w[2] = { point[p][0] - l[0][0], point[p][1] - l[0][1] };
return cross(v, w) > 0;
}
inline double point2line(int p, const double l[2][2])
{
double v[2] = { l[1][0] - l[0][0], l[1][1] - l[0][1] },
w[2] = { point[p][0] - l[0][0], point[p][1] - l[0][1] };
double ratio;
double pro[2]; //projection of p on l
printf("point2line (%d) %d %d line (%lf %lf) - (%lf %lf)\n",
p, point[p][0], point[p][1],
l[0][0], l[0][1], l[1][0], l[1][1]);
ratio = dot(v, w) / dist_squared(l[0], l[1]);
pro[0] = l[0][0] + v[0] * ratio;
pro[1] = l[0][1] + v[1] * ratio;
printf("ratio %lf. projection (%lf %lf)\n", ratio, pro[0], pro[1]);
printf("so dist is %lf\n", dist(p, pro));
return dist(p, pro);
}
void find_base()
{
base = 0;
for(int i = 1; i < points; i++)
{
if(point[i][0] < point[base][0])
base = i;
else if(point[i][0] == base && point[i][1] < point[base][1])
base = i;
}
printf("base %d (%d %d)\n", base, point[base][0], point[base][1]);
}
void turn_polar()
{
for(int i = 0; i < points; i++)
{
if(i == base)
{
polar_point[i].dist = 0;
polar_point[i].ang = -4; //it will always be first
}
else
{
polar_point[i].dist = dist(base, i);
polar_point[i].ang = atan2(point[i][1] - point[base][1], point[i][0] - point[base][0]);
}
polar_point[i].id = i;
}
}
void sort_points()
{
int i;
sort(polar_point, polar_point + points);
printf("sorted points:\n");
for(int i = 0; i < points; i++)
printf("(id %d) %d %d (ang %lf dist %lf)\n",
polar_point[i].id, point[ polar_point[i].id ][0], point[ polar_point[i].id ][1],
polar_point[i].ang, polar_point[i].dist);
printf("\n");
for(i = 0; i < points; i++)
sorted[i] = polar_point[i].id;
}
void calc_hull()
{
int i;
hull[0] = sorted[0];
hull[1] = sorted[1];
nhull = 2;
for(i = 2; i < points; i++)
{
if(nhull < 2)
{
printf("too few points. adding %d without thinking\n", sorted[i]);
hull[nhull++] = sorted[i];
continue;
}
printf("%d %d %d\n", hull[nhull - 2], hull[nhull - 1], sorted[i]);
if(leftof(hull[nhull - 2], hull[nhull - 1], sorted[i]))
{
//advance to next triplet
hull[nhull++] = sorted[i];
printf("ok\n");
}
else //this includes coliniarity
{
nhull--;
i--; //check this point again
printf("removed a point\n");
}
}
//hull[nhull++] = base; //always a non-detected hull member.
printf("hull (%d points):\n", nhull);
assert(nhull >= 3);
for(i = 0; i < nhull; i++)
printf("(%d) %d %d\n", hull[i], point[ hull[i] ][0], point[ hull[i] ][1]);
printf("\n");
}
/**
* Check if using a rectangle with one side containing [a,b] renders a better result.
*/
void check_using(int a, int b)
{
assert(a >= 0 && a < points);
assert(b >= 0 && b < points);
assert(a != b);
int i;
double dleft = 0, dright = 0,
perp_dleft = 0, perp_dright = 0,
total, perp_total, prod, tmp;
double line[2][2], perp_line[2][2];
//the line between point a and b
line[0][0] = point[a][0];
line[0][1] = point[a][1];
line[1][0] = point[b][0];
line[1][1] = point[b][1];
//the perpendicular line
perp_line[0][0] = point[a][0];
perp_line[0][1] = point[a][1];
if(line[1][1] - line[0][1] == 0) //line is parallel to Oy
{
perp_line[1][0] = perp_line[0][0]; //parallel to Ox
perp_line[1][1] = perp_line[0][1] + 1; //any
}
else
{
perp_line[1][0] = perp_line[0][0] + 1; //any
perp_line[1][1] = perp_line[0][1]
- (1.0 * (line[1][0] - line[0][0])) / (line[1][1] - line[0][1]);
}
printf("points %d %d. line (%lf %lf) - (%lf %lf) and (%lf %lf) - (%lf %lf)\n",
a, b,
line[0][0], line[0][1], line[1][0], line[1][1],
perp_line[0][0], perp_line[0][1], perp_line[1][0], perp_line[1][1]);
for(i = 0; i < nhull; i++)
{
tmp = point2line(hull[i], line);
if(leftof(hull[i], line))
{
if(tmp > dleft)
dleft = tmp;
}
else
{
if(tmp > dright)
dright = tmp;
}
tmp = point2line(hull[i], perp_line);
if(leftof(hull[i], perp_line))
{
if(tmp > perp_dleft)
perp_dleft = tmp;
}
else
{
if(tmp > perp_dright)
perp_dright = tmp;
}
printf("\n");
}
printf("dright %lf dleft %lf. perp_dright %lf perp_dleft %lf.\n",
dright, dleft, perp_dright, perp_dleft);
total = dright + dleft;
perp_total = perp_dright + perp_dleft;
printf("total %lf perp_total %lf\n", total, perp_total);
prod = total * perp_total;
printf("prod %lf\n", prod);
if(prod < ans)
ans = prod;
printf("------------------------------------------\n\n");
}
void go()
{
find_base();
turn_polar();
sort_points();
calc_hull();
assert(nhull >= 3);
ans = 1e20; //inf
for(int i = 0; i < nhull; i++)
check_using(hull[i], hull[ (i + 1) % nhull ]);
printf("final ans %lf\n", ans);
}
int main()
{
int i;
FILE *f = fopen("rubarba.in", "r");
if(!f) return 1;
fscanf(f, "%d", &points);
for(i = 0; i < points; i++)
fscanf(f, "%d%d", &point[i][0], &point[i][1]);
fclose(f);
f = fopen("rubarba.out", "w");
if(!f) return 1;
go();
fprintf(f, "%.2lf\n", ans);
fclose(f);
return 0;
}