Problem:
Problem J:
Cave Explorer
Mike Smith is a man exploring caves all over the world.
One day, he faced a scaring creature blocking his way. He got scared, but in short time he took
his knife and then slashed it to attempt to kill it. Then they were split into parts, which soon
died out but the largest one. He slashed the creature a couple of times more to make it small
enough, and finally became able to go forward.
Now let us think of his situation in a mathematical way. The creature is considered to be a
polygon, convex or concave. Mike slashes this creature straight with his knife in some direction.
We suppose here the direction is given for simpler settings, while the position is arbitrary. Then
all split parts but the largest one disappears.
Your task is to write a program that calculates the area of the remaining part when the creature
is slashed in such a way that the area is minimized.
Input
The input is a sequence of datasets. Each dataset is given in the following format:
n
v
x
v
y
x
1
y
1
...
x
n
y
n
The first line contains an integer
n
, the number of vertices of the polygon that represents the
shape of the creature (3 ≤
n
≤ 100). The next line contains two integers
v
x
and
v
y
, where
(
v
x
,
v
y
) denote a vector that represents the direction of the knife (-10000 ≤
v
x
,
v
y
≤ 10000,
v
x
2
+
v
y
2
> 0). Then
n
lines follow. The
i
-th line contains two integers
x
i
and
y
i
, where (
x
i
,
y
i
)
denote the coordinates of the
i
-th vertex of the polygon (0 ≤
x
i
,
y
i
≤ 10000).
The vertices are given in the counterclockwise order. You may assume the polygon is always
simple, that is, the edges do not touch or cross each other except for end points.
The input is terminated by a line with a zero. This should not be processed.
Output
For each dataset, print the minimum possible area in a line. The area may be printed with
an arbitrary number of digits after the decimal point, but should not contain an absolute error
greater than 10
-2
.
Sample Input
5
0 1
0 0
5 0
1 1
5 2
0 2
7
9999 9998
0 0
2 0
3 1
1 1
10000 9999
2 2
0 2
0
Output for the Sample Input
2.00
2.2500000

Submitted solutions:

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	int s = 0, e = Y.size() - 1, m = 0;
	while (s < e) {
		m = (s + e) >> 1;
		if (sign(y - Y[m]) > 0) s = m + 1;
		else e = m;
	}
	return s;
}

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld rad() const { return norm(atan2l(y, x)); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
};
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: L \n";
			ld y = Y[yi];
			//if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) { F.push_back(a); break; }
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: R \n";
			ld y = Y[yi];
			//if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) { F.push_back(a); break; }
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	if (limit < 10 || H.size() < 10) TOL = 1e-7;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		if (a1 > a2) s = m1;
		else e = m2;
	}
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 4020
final_rank: 15

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	int s = 0, e = Y.size() - 1, m = 0;
	while (s < e) {
		m = (s + e) >> 1;
		if (sign(y - Y[m]) > 0) s = m + 1;
		else e = m;
	}
	return s;
	//for (int i = 0; i < Y.size(); i++) {
	//	if (i == 0 && y < Y[i]) return i;
	//	if (eq(Y[i], y)) return i;
	//	else if (between(Y[i], Y[i + 1], y)) return i + 1;
	//}
	//return Y.size();
}

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld rad() const { return norm(atan2l(y, x)); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
};
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: L \n";
			ld y = Y[yi];
			//if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) { F.push_back(a); break; }
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: R \n";
			ld y = Y[yi];
			//if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) { F.push_back(a); break; }
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	if (limit < 10 || H.size() < 10) TOL = 1e-7;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		if (a1 > a2) s = m1;
		else e = m2;
	}
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3924
final_rank: 7

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	int s = 0, e = Y.size() - 1, m = 0;
	while (s < e) {
		m = (s + e) >> 1;
		if (sign(y - Y[m]) > 0) s = m + 1;
		else e = m;
	}
	return s;
	//for (int i = 0; i < Y.size(); i++) {
	//	if (i == 0 && y < Y[i]) return i;
	//	if (eq(Y[i], y)) return i;
	//	else if (between(Y[i], Y[i + 1], y)) return i + 1;
	//}
	//return Y.size();
}

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld rad() const { return norm(atan2l(y, x)); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
};
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: L \n";
			ld y = Y[yi];
			//if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: R \n";
			ld y = Y[yi];
			//if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	if (limit < 10 || H.size() < 10) TOL = 1e-7;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		if (a1 > a2) s = m1;
		else e = m2;
	}
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3916
final_rank: 6

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	int s = 0, e = Y.size() - 1, m = 0;
	while (s < e) {
		m = (s + e) >> 1;
		if (sign(y - Y[m]) > 0) s = m + 1;
		else e = m;
	}
	return s;
	//for (int i = 0; i < Y.size(); i++) {
	//	if (i == 0 && y < Y[i]) return i;
	//	if (eq(Y[i], y)) return i;
	//	else if (between(Y[i], Y[i + 1], y)) return i + 1;
	//}
	//return Y.size();
}

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld rad() const { return norm(atan2l(y, x)); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
};
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: L \n";
			//if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: R \n";
			ld y = Y[yi];
			//if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	if (limit < 10 || H.size() < 10) TOL = 1e-7;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		if (a1 > a2) s = m1;
		else e = m2;
	}
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3928
final_rank: 8

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	int s = 0, e = Y.size() - 1, m = 0;
	while (s < e) {
		m = (s + e) >> 1;
		if (sign(y - Y[m]) > 0) s = m + 1;
		else e = m;
	}
	return s;
	//for (int i = 0; i < Y.size(); i++) {
	//	if (i == 0 && y < Y[i]) return i;
	//	if (eq(Y[i], y)) return i;
	//	else if (between(Y[i], Y[i + 1], y)) return i + 1;
	//}
	//return Y.size();
}

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld rad() const { return norm(atan2l(y, x)); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
};
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R " << lt << " " << j << " " << k << " " << h << " " << y << "\n";
			//std::cout << "FUCK:: R \n";
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	if (limit < 10 || H.size() < 10) TOL = 1e-7;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		if (a1 > a2) s = m1;
		else e = m2;
	}
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3960
final_rank: 13

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld sq(ld x) { return (ld)x * x; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	int s = 0, e = Y.size() - 1, m = 0;
	while (s < e) {
		m = (s + e) >> 1;
		if (sign(y - Y[m]) > 0) s = m + 1;
		else e = m;
	}
	return s;
	//for (int i = 0; i < Y.size(); i++) {
	//	if (i == 0 && y < Y[i]) return i;
	//	if (eq(Y[i], y)) return i;
	//	else if (between(Y[i], Y[i + 1], y)) return i + 1;
	//}
	//return Y.size();
}

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrtl(Euc()); }
	ld rad() const { return norm(atan2l(y, x)); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = { 0, 0 };
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	bool f = 1;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	f = 1;
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << " " << Y[yi] << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	f = 1;
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "R:: \n";
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R \n";
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	if (limit < 10 || H.size() < 10) TOL = 1e-7;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		if (a1 > a2) s = m1;
		else e = m2;
	}
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	//if ((zero(v.y) && v.x < 0) || v.y < 0) v *= -1;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3936
final_rank: 9

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
typedef std::vector<bool> Vbool;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld sq(ld x) { return (ld)x * x; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	int s = 0, e = Y.size() - 1, m = 0;
	while (s < e) {
		m = (s + e) >> 1;
		if (sign(y - Y[m]) > 0) s = m + 1;
		else e = m;
	}
	return s;
	//for (int i = 0; i < Y.size(); i++) {
	//	if (i == 0 && y < Y[i]) return i;
	//	if (eq(Y[i], y)) return i;
	//	else if (between(Y[i], Y[i + 1], y)) return i + 1;
	//}
	//return Y.size();
}

#define RIGHT 1
#define LEFT 2

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return *this < p || *this == p; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ld xy() const { return x * y; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrtl(Euc()); }
	Pos unit() const { return *this / mag(); }
	ld rad() const { return norm(atan2l(y, x)); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	bool close(const Pos& p) const { return zero((*this - p).Euc()); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = { 0, 0 };
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ld cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { return sign(cross(d1, d2, d3)); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return sign(cross(d1, d2, d3, d4)); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
bool on_seg_strong(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d3, d2)) >= 0; }
bool on_seg_weak(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d2, d3)) > 0; }
bool collinear(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return !ccw(d1, d2, d3) && !ccw(d1, d2, d4); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld green(const Pos& s, const Pos& e) { Pos m = (s + e) * .5; return m.y * (s.x - e.x); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	bool f = 1;
	int rl = LEFT;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	f = 1;
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << " " << Y[yi] << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	f = 1;
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "R:: \n";
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R \n";
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	if (limit < 10 || H.size() < 10) TOL = 1e-7;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		if (a1 > a2) s = m1;
		else e = m2;
	}
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	if ((zero(v.y) && v.x < 0) || v.y < 0) v *= -1;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3844
final_rank: 4

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
typedef std::vector<bool> Vbool;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld sq(ld x) { return (ld)x * x; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	//int s = 0, e = Y.size() - 1, m = 0;
	//while (s < e) {
	//	m = (s + e) >> 1;
	//	if (sign(y - Y[m]) > 0) s = m + 1;
	//	else e = m;
	//}
	//return s;
	for (int i = 0; i < Y.size(); i++) {
		if (i == 0 && y < Y[i]) return i;
		if (eq(Y[i], y)) return i;
		else if (between(Y[i], Y[i + 1], y)) return i + 1;
	}
	return Y.size();
}

#define RIGHT 1
#define LEFT 2

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return *this < p || *this == p; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ld xy() const { return x * y; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrtl(Euc()); }
	Pos unit() const { return *this / mag(); }
	ld rad() const { return norm(atan2l(y, x)); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	bool close(const Pos& p) const { return zero((*this - p).Euc()); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = { 0, 0 };
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ld cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { return sign(cross(d1, d2, d3)); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return sign(cross(d1, d2, d3, d4)); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
bool on_seg_strong(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d3, d2)) >= 0; }
bool on_seg_weak(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d2, d3)) > 0; }
bool collinear(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return !ccw(d1, d2, d3) && !ccw(d1, d2, d4); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld green(const Pos& s, const Pos& e) { Pos m = (s + e) * .5; return m.y * (s.x - e.x); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	bool f = 1;
	int rl = LEFT;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	f = 1;
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << " " << Y[yi] << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			//if (A[I[k]] > 0) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	f = 1;
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "R:: \n";
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R \n";
			//if (yi <= 0) { F.push_back(a); break; }
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	//if (std::abs(s - e) < 5) TOL = 1e-5;
	//else if (std::abs(s - e) < 10) TOL = 1e-7;
	//else if (H.size() == 8) TOL = 1e-8;
	//else TOL = 1e-15;
	if (limit < 10 || H.size() < 10) TOL = 1e-7;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		//std::cout << "a1a2:: " << a1 << " " << a2 << "\n";
		if (a1 > a2) s = m1;
		else e = m2;
	}
	//std::cout << "a1a2::::::::::::::::" << a1 << " " << a2 << "\n";
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	if ((zero(v.y) && v.x < 0) || v.y < 0) v *= -1;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	//for (const Pos& p : H) std::cout << p << "\n";
	//std::cout << ternary_search(H) * .5 << "\n";
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	//freopen("../../../input_data/cave.txt", "r", stdin);
	//freopen("../../../input_data/cave.ret", "w", stdout);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3936
final_rank: 9

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
typedef std::vector<bool> Vbool;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld sq(ld x) { return (ld)x * x; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	//int s = 0, e = Y.size() - 1, m = 0;
	//while (s < e) {
	//	m = (s + e) >> 1;
	//	if (sign(y - Y[m]) > 0) s = m + 1;
	//	else e = m;
	//}
	//return s;
	for (int i = 0; i < Y.size(); i++) {
		if (i == 0 && y < Y[i]) return i;
		if (eq(Y[i], y)) return i;
		else if (between(Y[i], Y[i + 1], y)) return i + 1;
	}
	return Y.size();
}

#define RIGHT 1
#define LEFT 2

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return *this < p || *this == p; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ld xy() const { return x * y; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrtl(Euc()); }
	Pos unit() const { return *this / mag(); }
	ld rad() const { return norm(atan2l(y, x)); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	bool close(const Pos& p) const { return zero((*this - p).Euc()); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = { 0, 0 };
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ld cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { return sign(cross(d1, d2, d3)); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return sign(cross(d1, d2, d3, d4)); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
bool on_seg_strong(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d3, d2)) >= 0; }
bool on_seg_weak(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d2, d3)) > 0; }
bool collinear(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return !ccw(d1, d2, d3) && !ccw(d1, d2, d4); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld green(const Pos& s, const Pos& e) { Pos m = (s + e) * .5; return m.y * (s.x - e.x); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	bool f = 1;
	int rl = LEFT;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	f = 1;
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << " " << Y[yi] << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			//if (A[I[k]] > 0) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	f = 1;
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "R:: \n";
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R \n";
			//if (yi <= 0) { F.push_back(a); break; }
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	//if (std::abs(s - e) < 5) TOL = 1e-5;
	//else if (std::abs(s - e) < 10) TOL = 1e-7;
	//else if (H.size() == 8) TOL = 1e-8;
	//else TOL = 1e-15;
	if (limit < 10) TOL = 1e-7;
	else if (H.size() < 10) TOL = 1e-7;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		//std::cout << "a1a2:: " << a1 << " " << a2 << "\n";
		if (a1 > a2) s = m1;
		else e = m2;
	}
	//std::cout << "a1a2::::::::::::::::" << a1 << " " << a2 << "\n";
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	if ((zero(v.y) && v.x < 0) || v.y < 0) v *= -1;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	//for (const Pos& p : H) std::cout << p << "\n";
	//std::cout << ternary_search(H) * .5 << "\n";
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	//freopen("../../../input_data/cave.txt", "r", stdin);
	//freopen("../../../input_data/cave.ret", "w", stdout);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3848
final_rank: 5

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
typedef std::vector<bool> Vbool;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld sq(ld x) { return (ld)x * x; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	//int s = 0, e = Y.size() - 1, m = 0;
	//while (s < e) {
	//	m = (s + e) >> 1;
	//	if (sign(y - Y[m]) > 0) s = m + 1;
	//	else e = m;
	//}
	//return s;
	for (int i = 0; i < Y.size(); i++) {
		if (i == 0 && y < Y[i]) return i;
		if (eq(Y[i], y)) return i;
		else if (between(Y[i], Y[i + 1], y)) return i + 1;
	}
	return Y.size();
}

#define RIGHT 1
#define LEFT 2

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return *this < p || *this == p; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ld xy() const { return x * y; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrtl(Euc()); }
	Pos unit() const { return *this / mag(); }
	ld rad() const { return norm(atan2l(y, x)); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	bool close(const Pos& p) const { return zero((*this - p).Euc()); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = { 0, 0 };
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ld cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { return sign(cross(d1, d2, d3)); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return sign(cross(d1, d2, d3, d4)); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
bool on_seg_strong(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d3, d2)) >= 0; }
bool on_seg_weak(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d2, d3)) > 0; }
bool collinear(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return !ccw(d1, d2, d3) && !ccw(d1, d2, d4); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld green(const Pos& s, const Pos& e) { Pos m = (s + e) * .5; return m.y * (s.x - e.x); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	bool f = 1;
	int rl = LEFT;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	f = 1;
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << " " << Y[yi] << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			//if (A[I[k]] > 0) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	f = 1;
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "R:: \n";
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R \n";
			//if (yi <= 0) { F.push_back(a); break; }
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	//if (std::abs(s - e) < 5) TOL = 1e-5;
	//else if (std::abs(s - e) < 10) TOL = 1e-7;
	//else if (H.size() == 8) TOL = 1e-8;
	//else TOL = 1e-15;
	if (limit < 5) TOL = 1e-7;
	else if (limit < 10) TOL = 1e-7;
	else if (H.size() < 10) TOL = 1e-8;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		//std::cout << "a1a2:: " << a1 << " " << a2 << "\n";
		if (a1 > a2) s = m1;
		else e = m2;
	}
	//std::cout << "a1a2::::::::::::::::" << a1 << " " << a2 << "\n";
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	if ((zero(v.y) && v.x < 0) || v.y < 0) v *= -1;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	//for (const Pos& p : H) std::cout << p << "\n";
	//std::cout << ternary_search(H) * .5 << "\n";
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	//freopen("../../../input_data/cave.txt", "r", stdin);
	//freopen("../../../input_data/cave.ret", "w", stdout);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 4024
final_rank: 16

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
typedef std::vector<bool> Vbool;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld sq(ld x) { return (ld)x * x; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	//int s = 0, e = Y.size() - 1, m = 0;
	//while (s < e) {
	//	m = (s + e) >> 1;
	//	if (sign(y - Y[m]) > 0) s = m + 1;
	//	else e = m;
	//}
	//return s;
	for (int i = 0; i < Y.size(); i++) {
		if (i == 0 && y < Y[i]) return i;
		if (eq(Y[i], y)) return i;
		else if (between(Y[i], Y[i + 1], y)) return i + 1;
	}
	return Y.size();
}

#define RIGHT 1
#define LEFT 2

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return *this < p || *this == p; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ld xy() const { return x * y; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrtl(Euc()); }
	Pos unit() const { return *this / mag(); }
	ld rad() const { return norm(atan2l(y, x)); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	bool close(const Pos& p) const { return zero((*this - p).Euc()); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = { 0, 0 };
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ld cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { return sign(cross(d1, d2, d3)); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return sign(cross(d1, d2, d3, d4)); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
bool on_seg_strong(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d3, d2)) >= 0; }
bool on_seg_weak(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d2, d3)) > 0; }
bool collinear(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return !ccw(d1, d2, d3) && !ccw(d1, d2, d4); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld green(const Pos& s, const Pos& e) { Pos m = (s + e) * .5; return m.y * (s.x - e.x); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	bool f = 1;
	int rl = LEFT;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	f = 1;
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << " " << Y[yi] << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			//if (A[I[k]] > 0) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	f = 1;
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "R:: \n";
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R \n";
			//if (yi <= 0) { F.push_back(a); break; }
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	//if (std::abs(s - e) < 5) TOL = 1e-5;
	//else if (std::abs(s - e) < 10) TOL = 1e-7;
	//else if (H.size() == 8) TOL = 1e-8;
	//else TOL = 1e-15;
	if (limit < 5) TOL = 1e-7;
	else if (limit < 10) TOL = 1e-7;
	else if (H.size() <= 8) TOL = 1e-8;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		//std::cout << "a1a2:: " << a1 << " " << a2 << "\n";
		if (a1 > a2) s = m1;
		else e = m2;
	}
	//std::cout << "a1a2::::::::::::::::" << a1 << " " << a2 << "\n";
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	if ((zero(v.y) && v.x < 0) || v.y < 0) v *= -1;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	//for (const Pos& p : H) std::cout << p << "\n";
	//std::cout << ternary_search(H) * .5 << "\n";
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	//freopen("../../../input_data/cave.txt", "r", stdin);
	//freopen("../../../input_data/cave.ret", "w", stdout);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3980
final_rank: 14

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
typedef std::vector<bool> Vbool;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld sq(ld x) { return (ld)x * x; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	//int s = 0, e = Y.size() - 1, m = 0;
	//while (s < e) {
	//	m = (s + e) >> 1;
	//	if (sign(y - Y[m]) > 0) s = m + 1;
	//	else e = m;
	//}
	//return s;
	for (int i = 0; i < Y.size(); i++) {
		if (i == 0 && y < Y[i]) return i;
		if (eq(Y[i], y)) return i;
		else if (between(Y[i], Y[i + 1], y)) return i + 1;
	}
	return Y.size();
}

#define RIGHT 1
#define LEFT 2

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return *this < p || *this == p; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ld xy() const { return x * y; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrtl(Euc()); }
	Pos unit() const { return *this / mag(); }
	ld rad() const { return norm(atan2l(y, x)); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	bool close(const Pos& p) const { return zero((*this - p).Euc()); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = { 0, 0 };
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ld cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { return sign(cross(d1, d2, d3)); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return sign(cross(d1, d2, d3, d4)); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
bool on_seg_strong(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d3, d2)) >= 0; }
bool on_seg_weak(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d2, d3)) > 0; }
bool collinear(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return !ccw(d1, d2, d3) && !ccw(d1, d2, d4); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld green(const Pos& s, const Pos& e) { Pos m = (s + e) * .5; return m.y * (s.x - e.x); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	bool f = 1;
	int rl = LEFT;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	f = 1;
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << " " << Y[yi] << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			//if (A[I[k]] > 0) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	f = 1;
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "R:: \n";
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R \n";
			//if (yi <= 0) { F.push_back(a); break; }
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	//if (std::abs(s - e) < 5) TOL = 1e-5;
	//else if (std::abs(s - e) < 10) TOL = 1e-7;
	//else if (H.size() == 8) TOL = 1e-8;
	//else TOL = 1e-15;
	if (limit < 5) TOL = 1e-7;
	else if (limit < 10) TOL = 1e-7;
	else if (H.size() == 8) TOL = 1e-8;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		//std::cout << "a1a2:: " << a1 << " " << a2 << "\n";
		if (a1 > a2) s = m1;
		else e = m2;
	}
	//std::cout << "a1a2::::::::::::::::" << a1 << " " << a2 << "\n";
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	if ((zero(v.y) && v.x < 0) || v.y < 0) v *= -1;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	//for (const Pos& p : H) std::cout << p << "\n";
	//std::cout << ternary_search(H) * .5 << "\n";
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	//freopen("../../../input_data/cave.txt", "r", stdin);
	//freopen("../../../input_data/cave.ret", "w", stdout);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 3952
final_rank: 11

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
typedef std::vector<bool> Vbool;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld sq(ld x) { return (ld)x * x; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	int s = 0, e = Y.size() - 1, m = 0;
	while (s < e) {
		m = (s + e) >> 1;
		if (sign(y - Y[m]) > 0) s = m + 1;
		else e = m;
	}
	return s;
	//for (int i = 0; i < Y.size(); i++) {
	//	if (i == 0 && y < Y[i]) return i;
	//	if (eq(Y[i], y)) return i;
	//	else if (between(Y[i], Y[i + 1], y)) return i + 1;
	//}
	//return Y.size();
}

#define RIGHT 1
#define LEFT 2

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return *this < p || *this == p; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ld xy() const { return x * y; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrtl(Euc()); }
	Pos unit() const { return *this / mag(); }
	ld rad() const { return norm(atan2l(y, x)); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	bool close(const Pos& p) const { return zero((*this - p).Euc()); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = { 0, 0 };
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ld cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { return sign(cross(d1, d2, d3)); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return sign(cross(d1, d2, d3, d4)); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
bool on_seg_strong(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d3, d2)) >= 0; }
bool on_seg_weak(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d2, d3)) > 0; }
bool collinear(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return !ccw(d1, d2, d3) && !ccw(d1, d2, d4); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld green(const Pos& s, const Pos& e) { Pos m = (s + e) * .5; return m.y * (s.x - e.x); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	bool f = 1;
	int rl = LEFT;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	f = 1;
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << " " << Y[yi] << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			//if (A[I[k]] > 0) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	f = 1;
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "R:: \n";
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R \n";
			//if (yi <= 0) { F.push_back(a); break; }
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	//if (std::abs(s - e) < 5) TOL = 1e-5;
	//else if (std::abs(s - e) < 10) TOL = 1e-7;
	//else if (H.size() == 8) TOL = 1e-8;
	//else TOL = 1e-15;
	if (limit < 5) TOL = 1e-7;
	else if (limit < 10) TOL = 1e-7;
	else if (H.size() == 8) TOL = 1e-8;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		//std::cout << "a1a2:: " << a1 << " " << a2 << "\n";
		if (a1 > a2) s = m1;
		else e = m2;
	}
	//std::cout << "a1a2::::::::::::::::" << a1 << " " << a2 << "\n";
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	if ((zero(v.y) && v.x < 0) || v.y < 0) v *= -1;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	//for (const Pos& p : H) std::cout << p << "\n";
	//std::cout << ternary_search(H) * .5 << "\n";
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	//freopen("../../../input_data/cave.txt", "r", stdin);
	//freopen("../../../input_data/cave.ret", "w", stdout);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer
accuracy: 1
time_ms: 10
memory_kb: 4024
final_rank: 16

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
typedef std::vector<bool> Vbool;
const ld INF = 1e17;
ld TOL = 1e-15;
const ld PI = acos(-1);
const int LEN = 105;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& u, const ld& v) { return zero(u - v); }
inline bool between(ld s, ld e, const ld& x) { if (e < s) std::swap(s, e); return sign(x - s) > 0 && sign(e - x) > 0; }
inline ld sq(ld x) { return (ld)x * x; }
inline ld norm(ld th) {
	while (th < 0) th += 2 * PI;
	while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
	return th;
}
int find_y(const Vld& Y, const ld& y) {
	//int s = 0, e = Y.size() - 1, m = 0;
	//while (s < e) {
	//	m = (s + e) >> 1;
	//	if (sign(y - Y[m]) > 0) s = m + 1;
	//	else e = m;
	//}
	//return s;
	for (int i = 0; i < Y.size(); i++) {
		if (i == 0 && y < Y[i]) return i;
		if (eq(Y[i], y)) return i;
		else if (between(Y[i], Y[i + 1], y)) return i + 1;
	}
	return Y.size();
}

#define RIGHT 1
#define LEFT 2

int N;
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return *this < p || *this == p; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ld xy() const { return x * y; }
	Pos rot(ld the) const { return { x * (ld)cosl(the) - y * (ld)sinl(the), x * (ld)sinl(the) + y * (ld)cosl(the) }; }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrtl(Euc()); }
	Pos unit() const { return *this / mag(); }
	ld rad() const { return norm(atan2l(y, x)); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	bool close(const Pos& p) const { return zero((*this - p).Euc()); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = { 0, 0 };
typedef std::vector<Pos> Polygon;
Polygon R[LEN], L[LEN];
int rt, lt;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ld cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { return sign(cross(d1, d2, d3)); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return sign(cross(d1, d2, d3, d4)); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ld dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
bool on_seg_strong(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d3, d2)) >= 0; }
bool on_seg_weak(const Pos& d1, const Pos& d2, const Pos& d3) { return !ccw(d1, d2, d3) && sign(dot(d1, d2, d3)) > 0; }
bool collinear(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return !ccw(d1, d2, d3) && !ccw(d1, d2, d4); }
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) { ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2); return (p1 * a2 + p2 * a1) / (a1 + a2); }
ld green(const Pos& s, const Pos& e) { Pos m = (s + e) * .5; return m.y * (s.x - e.x); }
ld area(const Polygon& H) {
	ld a = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) a += H[i] / H[(i + 1) % sz];
	return a;
}
ld largest(Polygon H, const ld& x) {
	Pos s = Pos(x, -1), e = Pos(x, 1);
	ld ret = 0;
	int i, sz = H.size();
	for (i = 0; i < sz; i++) if (eq(H[i].x, x) || between(H[i].x, H[(i + 1) % sz].x, x)) break;
	rt = lt = 0;
	Polygon tmp;
	bool f = 1;
	int rl = LEFT;
	if (!eq(H[i].x, x)) {
		tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		i = (i + 1) % sz;
	}
	else if (eq(H[i].x, x)) {
		if (eq(H[(i + 1) % sz].x, x)) {
			i = (i + 1) % sz;
		}
		tmp.push_back(H[i]);
		i = (i + 1) % sz;
	}
	for (int _ = 0; _ < sz; _++, i = (i + 1) % sz) {
		if (eq(H[i].x, x)) {
			tmp.push_back(H[i]);
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			if (eq(H[(i + 1) % sz].x, x)) _++, i = (i + 1) % sz;
			tmp.clear();
			tmp.push_back(H[i]);
		}
		else if (between(H[i].x, H[(i + 1) % sz].x, x)) {
			tmp.push_back(H[i]);
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
			if (tmp[1].x < x) L[lt++] = tmp;
			else if (tmp[1].x > x) R[rt++] = tmp;
			tmp.clear();
			tmp.push_back(intersection(s, e, H[i], H[(i + 1) % sz]));
		}
		else tmp.push_back(H[i]);
	}

	//std::cout << "DEBUG:: \n";
	//std::cout << "x:: " << x << "\n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << j << "]\n";
	//	for (const Pos& p : L[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << j << "]\n";
	//	for (const Pos& p : R[j]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";

	Vld F, A, Y;
	Vint I;
	I.resize(lt);
	for (int j = 0; j < lt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = L[p];
		const Polygon& Q = L[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(lt, 0);
	f = 1;
	for (int j = 0; j < lt; j++) {
		i = I[j];
		A[i] = area(L[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(L[i][0].y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "L:: \n";
	//for (int j = 0; j < lt; j++) {
	//	std::cout << "L[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	//std::cout << "DEBUG:: \n";
	for (int j = 0; j < lt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld h = L[i][0].y;
		ld a = A[i];
		int yi = find_y(Y, L[i].back().y);
		int k = j + 1;
		while (1) {
			ld y = Y[yi];
			//std::cout << "FUCK:: L " << lt << " " << j << " " << k << " " << h << " " << y << " " << Y[yi] << "\n";
			//std::cout << "FUCK:: L \n";
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < lt && !eq(y, L[I[k]][0].y)) k++;
			if (k >= I.size()) break;
			//if (A[I[k]] > 0) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, L[I[k]].back().y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	Y.clear();
	I.resize(rt);
	for (int j = 0; j < rt; j++) I[j] = j;
	std::sort(I.begin(), I.end(), [&](const int& p, const int& q) -> bool {
		const Polygon& P = R[p];
		const Polygon& Q = R[q];
		ld py = P[0].y < P.back().y ? P[0].y : P.back().y;
		ld qy = Q[0].y < Q.back().y ? Q[0].y : Q.back().y;
		return py < qy;
		});
	A.resize(rt, 0);
	f = 1;
	for (int j = 0; j < rt; j++) {
		i = I[j];
		A[i] = area(R[i]);
		if (A[i] < 0) f = 0;
		Y.push_back(R[i].back().y);
	}
	std::sort(Y.begin(), Y.end());
	//std::cout << "DEBUG:: \n";
	//std::cout << "R:: \n";
	//for (int j = 0; j < rt; j++) {
	//	std::cout << "R[" << I[j] << "]\n";
	//	for (const Pos& p : L[I[j]]) std::cout << " (" << p.x << ", " << p.y << "),\n";
	//}
	for (int j = 0; j < rt; j++) {
		i = I[j];
		if (A[i] < 0) continue;
		ld a = A[i];
		ld h = R[i].back().y;
		int yi = find_y(Y, R[i][0].y);
		int k = j + 1;
		while (1) {
			//std::cout << "FUCK:: R \n";
			//if (yi <= 0) { F.push_back(a); break; }
			ld y = Y[yi];
			if (sign(y - h) > 0) { F.push_back(a); break; }
			if (eq(y, h)) { F.push_back(a); break; }
			while (k < rt && !eq(y, R[I[k]].back().y)) k++;
			if (k >= I.size()) break;
			if (A[I[k]] > 0) { F.push_back(a); break; }
			if (A[I[k]] < 0) a += A[I[k]];
			yi = find_y(Y, R[I[k]][0].y);
			if (A[I[k]] < 0 && eq(Y[yi], y)) yi++;
		}
	}
	std::sort(F.rbegin(), F.rend());
	return F[0];
}
ld ternary_search(const Polygon& H) {
	assert(H.size() >= 3);
	ld s = INF, e = -INF;
	ld sy = INF, ey = -INF;
	for (const Pos& p : H) {
		s = std::min(s, p.x), e = std::max(e, p.x);
		sy = std::min(s, p.x), ey = std::max(e, p.x);
	}
	ld limit = std::max(std::abs(s - e), std::abs(sy - ey));
	//if (std::abs(s - e) < 5) TOL = 1e-5;
	//else if (std::abs(s - e) < 10) TOL = 1e-7;
	//else if (H.size() == 8) TOL = 1e-8;
	//else TOL = 1e-15;
	if (limit < 5) TOL = 1e-7;
	else if (limit < 10) TOL = 1e-7;
	else if (H.size() == 8) TOL = 1e-8;
	else TOL = 1e-15;
	s += TOL;
	e -= TOL;
	ld a1 = 0, a2 = 0;
	while (std::abs(e - s) > 1e-8) {
		ld m1 = (s + s + e) / 3;
		ld m2 = (s + e + e) / 3;
		a1 = largest(H, m1);
		a2 = largest(H, m2);
		//std::cout << "a1a2:: " << a1 << " " << a2 << "\n";
		if (a1 > a2) s = m1;
		else e = m2;
	}
	//std::cout << "a1a2::::::::::::::::" << a1 << " " << a2 << "\n";
	return largest(H, (s + e) * .5);
}
Vld ANS;
bool query() {
	std::cin >> N;
	if (!N) return 0;
	Pos v;
	std::cin >> v;
	if ((zero(v.y) && v.x < 0) || v.y < 0) v *= -1;
	ld t = v.rad();
	t = norm(PI * .5 - t);
	Polygon H(N);
	for (Pos& p : H) std::cin >> p, p = p.rot(t);
	//for (const Pos& p : H) std::cout << p << "\n";
	//std::cout << ternary_search(H) * .5 << "\n";
	ANS.push_back(ternary_search(H) * .5);
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	std::cout << std::fixed;
	std::cout.precision(15);
	//freopen("../../../input_data/cave.txt", "r", stdin);
	//freopen("../../../input_data/cave.ret", "w", stdout);
	while (query());
	for (const ld& a : ANS) std::cout << a << "\n";
	return;
}
int main() { solve(); return 0; }//boj13816 Cave Explorer

/*
* 
10
1 9998
0 0
1 9999
2 0
3 9999
4 0
5 10000
4 1
3 10000
2 1
1 10000
ans 1.4999749962
ret 2.500075061

8
1 1
0 0
9999 0
1 1
10000 0
10000 10000
1 10000
9999 9999
0 10000

*/
accuracy: 1
time_ms: 10
memory_kb: 3952
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;


#define SIZE 205
#define EPS 0.00001
#define EPS2 0.000000000001

enum Type{
	FIRST,
	SECOND,
};

struct Point{
	Point(long double arg_x,long double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (long double a){ return Point(a*x,a*y); }
	Point operator / (long double a){ return Point(x/a,y/a); }

	long double abs(){ return sqrt(norm()); }
	long double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(y-p.y) > EPS2){

			return y < p.y;
		}else{

			return x < p.x;
		}
	}

	bool operator == (const Point &p) const{
		double a = x-p.x,b = y-p.y;
		return sqrt(a*a+b*b) < EPS;
	}

	void debug(){

		printf("(%.12Lf,%.12Lf)\n",x,y);
	}

	long double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3Lf,%.3Lf)-(%.3Lf,%.3Lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

struct Info{

	Point p;
	bool is_cut;
};

struct Data{
	Data(Point arg_p,long double arg_index){
		p = arg_p;
		index = arg_index;
	}
	bool operator<(const struct Data &arg) const{

		return p < arg.p;
	}
	bool operator==(const struct Data &arg) const{

		return index == arg.index;
	}

	Point p;
	int index;
};

struct VALUE{
	VALUE(long double arg_value){

		value = arg_value;
	}
	bool operator<(const struct VALUE &arg) const{

		return value < arg.value;
	}
	bool operator==(const struct VALUE &arg) const{

		return fabs(value-arg.value) < EPS2;
	}

	long double value;
};

struct Edge{
	Edge(int arg_to,Type arg_type){
		to = arg_to;
		type = arg_type;
	}
	int to;
	Type type;
};

int N;
int num_point;
long double NUM = 1000000;
vector<int> P;
Point point[205];


long double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

long double abs(Vector a){
	return sqrt(norm(a));
}

long double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

long double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS2)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS2)return CLOCKWISE;
	if(dot(a,b) < -EPS2)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

long double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//切片を求める関数
long double calc_add(Line line){

	long double slope = calc_slope(line);

	if(fabs(slope-DBL_MAX) < EPS){

		return DBL_MAX;

	}else if(fabs(slope) < EPS){

		return line.p[0].y;

	}else{

		return line.p[0].y-slope*line.p[0].x;
	}
}


int func(long double x1,long double y1,long double x2, long double y2, long double xp, long double yp){
	long double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

long double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
long double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
long double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
long double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(long double x1,long double x2,long double x3,long double x4,long double y1,long double y2,long double y3,long double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

long double calc_S(Polygon g){

	int N = g.size();
	long double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}


/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS2 && dot(a,b) < EPS2)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS2 && EPS2 < b.y && cross(a,b) > EPS2) x = !x;
	}
	return (x ? 2:0);
}


//2つのvectorがなすラジアンを求める関数
long double calc_rad(Vector vec1,Vector vec2){

	long double tmp = dot(vec1,vec2)/(abs(vec1)*abs(vec2));

	if(fabs(tmp+1.0) < EPS2){

		return M_PI;
	}

	if(fabs(tmp-1.0) < EPS2){

		return  0.0;
	}

	return acos(dot(vec1,vec2)/(abs(vec1)*abs(vec2)));
}

//3点がなすラジアンを求める関数(ccw(base,a,b) == CCW)
long double calc_rad(Point base,Point a,Point b){

	Vector vec1 = b-base;
	Vector vec2 = a-base;

	return calc_rad(vec1,vec2);
}


long double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

long double calc_max_S(long double SLOPE,long double add){

	int num_info = 0;
	int table[205];
	Info info[205];
	bool check[205];
	vector<Edge> G[205];

	Line base_line;

	if(fabs(SLOPE-DBL_MAX) < EPS){ //垂直

		base_line = Line(Point(add,-NUM),Point(add,NUM));

	}else{

		base_line = Line(Point(-NUM,-NUM*SLOPE+add),Point(NUM,NUM*SLOPE+add));
	}

	for(int i = 0; i < num_point; i++){

		info[i].p = point[i];
		info[i].is_cut = false;
		num_info++;
	}

	vector<int> work_P;

	vector<Data> CROSS;

	int COUNT = 0;

	for(int i = 0; i < N; i++){

		work_P.push_back(P[i]);

		Line work_line = Line(point[i],point[(i+1)%N]);

		//work_line.outPut();
		long double tmp_slope = calc_slope(work_line);

		if(fabs(SLOPE-DBL_MAX) < EPS){

			if(fabs(work_line.p[0].x-add) < EPS|| fabs(work_line.p[1].x-add) < EPS){


			}else{

				if(!is_Cross(base_line,work_line)){

					continue;
				}
			}

		}else{
			if(!is_Cross(base_line,work_line)){

				continue;
			}
		}

		if(fabs(SLOPE-tmp_slope)  < EPS2){ //★★切断線とポリゴンの辺が平行(交差するので切片もおなじ)★★

			info[i].is_cut = true;
			info[(i+1)%N].is_cut = true;

			CROSS.push_back(Data(info[i].p,i));
			CROSS.push_back(Data(info[(i+1)%N].p,(i+1)%N));

		}else{ //傾きが異なる

			Point cross_p = calc_Cross_Point(base_line,work_line);

			if(cross_p == point[i]){

				info[i].is_cut = true;

				CROSS.push_back(Data(info[i].p,i));

			}else if(cross_p == point[(i+1)%N]){

				info[(i+1)%N].is_cut = true;

				CROSS.push_back(Data(info[(i+1)%N].p,(i+1)%N));

			}else{  //線分の途中に交点が来る

				info[num_info].p = cross_p;
				info[num_info].is_cut = true;

				work_P.push_back(num_info);

				CROSS.push_back(Data(cross_p,num_info));

				num_info++;
			}
		}
	}



	for(int i = 0; i < work_P.size(); i++){

		G[i].push_back(Edge((i+1)%work_P.size(),FIRST));
	}

	for(int i = 0; i < work_P.size(); i++){

		table[work_P[i]] = i;
	}

	Polygon poly;
	for(int i = 0; i < N; i++){

		poly.push_back(point[i]);
	}

	sort(CROSS.begin(),CROSS.end());
	CROSS.erase(unique(CROSS.begin(),CROSS.end()),CROSS.end());

	for(int i = 1; i < CROSS.size(); i++){

		Point mid_p = (info[CROSS[i-1].index].p+info[CROSS[i].index].p)/2;

		int tmp = contains(poly,mid_p);

		if(tmp != 0){ //内部か辺

			G[table[CROSS[i-1].index]].push_back(Edge(table[CROSS[i].index],SECOND));
			G[table[CROSS[i].index]].push_back(Edge(table[CROSS[i-1].index],SECOND));
		}
	}

	long double ret = 0;

	for(int i = 0; i < num_info; i++){

		check[i] = false;
	}

	for(int i = 0; i < num_info; i++){
		if(check[work_P[i]] || (info[work_P[i]].is_cut && G[i].size() > 1))continue;

		Polygon work_poly;
		Point start = info[work_P[i]].p;
		work_poly.push_back(start);

		check[work_P[i]] = true;

		int tmp_index = (i+1)%work_P.size();
		int tmp_next;

		int pre = i;

		int debug = 0;

		while(true){

			debug++;

			if(debug > work_P.size()+2){
				
				return BIG_NUM;
			}

			work_poly.push_back(info[work_P[tmp_index]].p);
			check[work_P[tmp_index]] = true;

			if(info[work_P[tmp_index]].is_cut && G[tmp_index].size() > 1){

				long double min_rad_cut = BIG_NUM;
				long double min_rad_not = BIG_NUM;
				int min_index_cut = -1,min_index_not = -1;

				for(int k = 0; k < G[tmp_index].size(); k++){

					int next = G[tmp_index][k].to;
					if(next == pre)continue;

					long double tmp_rad;
					if(ccw(info[work_P[tmp_index]].p,
							info[work_P[next]].p,info[work_P[pre]].p) == COUNTER_CLOCKWISE){

						tmp_rad = calc_rad(info[work_P[tmp_index]].p,info[work_P[next]].p,info[work_P[pre]].p);

					}else{

						tmp_rad = 2*M_PI- calc_rad(info[work_P[tmp_index]].p,info[work_P[pre]].p,info[work_P[next]].p);
					}

					if(G[tmp_index][k].type == SECOND){

						if(min_rad_cut > tmp_rad){
							min_rad_cut = tmp_rad;
							min_index_cut = next;
						}

					}else{

						if(min_rad_not > tmp_rad){
							min_rad_not = tmp_rad;
							min_index_not = next;
						}
					}
				}

				if(min_index_cut != -1 && min_index_not != -1 && fabs(min_rad_cut-min_rad_not) < EPS){

					tmp_next = min_index_cut;
				}else{

					if(min_rad_cut < min_rad_not){

						tmp_next = min_index_cut;

					}else{

						tmp_next = min_index_not;
					}
				}

			}else{

				tmp_next = (tmp_index+1)%work_P.size();
			}

			if(tmp_next == i)break;

			pre = tmp_index;
			tmp_index = tmp_next;
		}

		COUNT++;
		ret = max(ret,calc_S(work_poly));
	}

	if(COUNT == 0){

		return BIG_NUM;
	}

	return ret;
}


void func(){

	P.clear();
	num_point = 0;

	long double Vx,Vy;
	scanf("%Lf %Lf",&Vx,&Vy);

	long double SLOPE = calc_slope(Line(Point(0,0),Point(Vx,Vy)));

	for(int i = 0; i < N; i++){

		scanf("%Lf %Lf",&point[i].x,&point[i].y);
		num_point++;
	}
	for(int i = 0; i < N; i++){

		P.push_back(i);
	}

	vector<VALUE> V;

	//各点を通る、直線の切片またはX座標(傾きが垂直な場合)を求める
	for(int i = 0; i < num_point; i++){
		if(fabs(SLOPE-DBL_MAX) < EPS){

			V.push_back(VALUE(point[i].x));
		}else{


			V.push_back(VALUE(point[i].y-SLOPE*point[i].x));
		}
	}

	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());

	long double ans = BIG_NUM;

	for(int i = 1; i < V.size(); i++){

		long double L = V[i-1].value,R = V[i].value;

		for(int loop = 0; loop < 100; loop++){

			long double mid1 = (2.0*L+R)/3.0;
			long double mid2 = (1.0*L+2.0*R)/3.0;

			long double S1 = calc_max_S(SLOPE,mid1);
			long double S2 = calc_max_S(SLOPE,mid2);

			ans = min(ans,min(S1,S2));

			if(S1 <= S2){

				R = mid2;
			}else{

				L = mid1;
			}

			if(fabs(R-L) < EPS2)break;
		}
	}

	printf("%.10Lf\n",ans);
}


int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 5010
memory_kb: 3284
final_rank: 18

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;


#define SIZE 205
#define EPS 0.00001
#define EPS2 0.000000000001

enum Type{
	FIRST,
	SECOND,
};

struct Point{
	Point(long double arg_x,long double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (long double a){ return Point(a*x,a*y); }
	Point operator / (long double a){ return Point(x/a,y/a); }

	long double abs(){ return sqrt(norm()); }
	long double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		double a = x-p.x,b = y-p.y;
		return sqrt(a*a+b*b) < EPS;
	}

	void debug(){

		printf("(%.12Lf,%.12Lf)\n",x,y);
	}

	long double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3Lf,%.3Lf)-(%.3Lf,%.3Lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

struct Info{

	Point p;
	bool is_cut;
};

struct Data{
	Data(Point arg_p,long double arg_index){
		p = arg_p;
		index = arg_index;
	}
	bool operator<(const struct Data &arg) const{

		return p < arg.p;
	}
	bool operator==(const struct Data &arg) const{

		return index == arg.index;
	}

	Point p;
	int index;
};

struct VALUE{
	VALUE(long double arg_value){

		value = arg_value;
	}
	bool operator<(const struct VALUE &arg) const{

		return value < arg.value;
	}
	bool operator==(const struct VALUE &arg) const{

		return fabs(value-arg.value) < EPS;
	}

	long double value;
};

struct Edge{
	Edge(int arg_to,Type arg_type){
		to = arg_to;
		type = arg_type;
	}
	int to;
	Type type;
};

int N;
int num_point;
long double NUM = 1000000;
vector<int> P;
Point point[205];


long double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

long double abs(Vector a){
	return sqrt(norm(a));
}

long double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

long double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS2)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS2)return CLOCKWISE;
	if(dot(a,b) < -EPS2)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

long double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//切片を求める関数
long double calc_add(Line line){

	long double slope = calc_slope(line);

	if(fabs(slope-DBL_MAX) < EPS){

		return DBL_MAX;

	}else if(fabs(slope) < EPS){

		return line.p[0].y;

	}else{

		return line.p[0].y-slope*line.p[0].x;
	}
}


int func(long double x1,long double y1,long double x2, long double y2, long double xp, long double yp){
	long double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

long double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
long double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
long double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
long double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(long double x1,long double x2,long double x3,long double x4,long double y1,long double y2,long double y3,long double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

long double calc_S(Polygon g){

	int N = g.size();
	long double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}


/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS2 && dot(a,b) < EPS2)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS2 && EPS2 < b.y && cross(a,b) > EPS2) x = !x;
	}
	return (x ? 2:0);
}


//2つのvectorがなすラジアンを求める関数
long double calc_rad(Vector vec1,Vector vec2){

	long double tmp = dot(vec1,vec2)/(abs(vec1)*abs(vec2));

	if(fabs(tmp+1.0) < EPS2){

		return M_PI;
	}

	if(fabs(tmp-1.0) < EPS2){

		return  0.0;
	}

	return acos(dot(vec1,vec2)/(abs(vec1)*abs(vec2)));
}

//3点がなすラジアンを求める関数(ccw(base,a,b) == CCW)
long double calc_rad(Point base,Point a,Point b){

	Vector vec1 = b-base;
	Vector vec2 = a-base;

	return calc_rad(vec1,vec2);
}


long double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

long double calc_max_S(long double SLOPE,long double add){

	int num_info = 0;
	int table[205];
	Info info[205];
	bool check[205];
	vector<Edge> G[205];

	Line base_line;

	if(fabs(SLOPE-DBL_MAX) < EPS){ //垂直

		base_line = Line(Point(add,-NUM),Point(add,NUM));

	}else{

		base_line = Line(Point(-NUM,-NUM*SLOPE+add),Point(NUM,NUM*SLOPE+add));
	}

	for(int i = 0; i < num_point; i++){

		info[i].p = point[i];
		info[i].is_cut = false;
		num_info++;
	}

	vector<int> work_P;

	vector<Data> CROSS;

	int COUNT = 0;

	for(int i = 0; i < N; i++){

		work_P.push_back(P[i]);

		Line work_line = Line(point[i],point[(i+1)%N]);

		//work_line.outPut();
		long double tmp_slope = calc_slope(work_line);

		if(fabs(SLOPE-DBL_MAX) < EPS){

			if(fabs(work_line.p[0].x-add) < EPS|| fabs(work_line.p[1].x-add) < EPS){


			}else{

				if(!is_Cross(base_line,work_line)){

					continue;
				}
			}

		}else{
			if(!is_Cross(base_line,work_line)){

				continue;
			}
		}

		if(fabs(SLOPE-tmp_slope)  < EPS2){ //★★切断線とポリゴンの辺が平行(交差するので切片もおなじ)★★

			info[i].is_cut = true;
			info[(i+1)%N].is_cut = true;

			CROSS.push_back(Data(info[i].p,i));
			CROSS.push_back(Data(info[(i+1)%N].p,(i+1)%N));

		}else{ //傾きが異なる

			Point cross_p = calc_Cross_Point(base_line,work_line);

			if(cross_p == point[i]){

				info[i].is_cut = true;

				CROSS.push_back(Data(info[i].p,i));

			}else if(cross_p == point[(i+1)%N]){

				info[(i+1)%N].is_cut = true;

				CROSS.push_back(Data(info[(i+1)%N].p,(i+1)%N));

			}else{  //線分の途中に交点が来る

				info[num_info].p = cross_p;
				info[num_info].is_cut = true;

				work_P.push_back(num_info);

				CROSS.push_back(Data(cross_p,num_info));

				num_info++;
			}
		}
	}



	for(int i = 0; i < work_P.size(); i++){

		G[i].push_back(Edge((i+1)%work_P.size(),FIRST));
	}

	for(int i = 0; i < work_P.size(); i++){

		table[work_P[i]] = i;
	}

	Polygon poly;
	for(int i = 0; i < N; i++){

		poly.push_back(point[i]);
	}

	sort(CROSS.begin(),CROSS.end());
	CROSS.erase(unique(CROSS.begin(),CROSS.end()),CROSS.end());

	for(int i = 1; i < CROSS.size(); i++){

		Point mid_p = (info[CROSS[i-1].index].p+info[CROSS[i].index].p)/2;

		int tmp = contains(poly,mid_p);

		if(tmp != 0){ //内部か辺

			G[table[CROSS[i-1].index]].push_back(Edge(table[CROSS[i].index],SECOND));
			G[table[CROSS[i].index]].push_back(Edge(table[CROSS[i-1].index],SECOND));
		}
	}


	long double ret = 0;

	for(int i = 0; i < num_info; i++){

		check[i] = false;
	}


	for(int i = 0; i < num_info; i++){
		if(check[work_P[i]] || (info[work_P[i]].is_cut && G[i].size() > 1))continue;

		Polygon work_poly;
		Point start = info[work_P[i]].p;
		work_poly.push_back(start);

		check[work_P[i]] = true;

		int tmp_index = (i+1)%work_P.size();
		int tmp_next;

		int pre = i;

		int debug = 0;

		while(true){

			debug++;

			if(debug > work_P.size()+2){
				return BIG_NUM;
			}

			work_poly.push_back(info[work_P[tmp_index]].p);
			check[work_P[tmp_index]] = true;

			if(info[work_P[tmp_index]].is_cut && G[tmp_index].size() > 1){

				long double min_rad_cut = BIG_NUM;
				long double min_rad_not = BIG_NUM;
				int min_index_cut = -1,min_index_not = -1;

				for(int k = 0; k < G[tmp_index].size(); k++){

					int next = G[tmp_index][k].to;
					if(next == pre)continue;

					long double tmp_rad;
					if(ccw(info[work_P[tmp_index]].p,
							info[work_P[next]].p,info[work_P[pre]].p) == COUNTER_CLOCKWISE){

						tmp_rad = calc_rad(info[work_P[tmp_index]].p,info[work_P[next]].p,info[work_P[pre]].p);


					}else{
						tmp_rad = 2*M_PI- calc_rad(info[work_P[tmp_index]].p,info[work_P[pre]].p,info[work_P[next]].p);
					}

					if(G[tmp_index][k].type == SECOND){

						if(min_rad_cut > tmp_rad){
							min_rad_cut = tmp_rad;
							min_index_cut = next;
						}

					}else{

						if(min_rad_not > tmp_rad){
							min_rad_not = tmp_rad;
							min_index_not = next;
						}
					}
				}

				if(min_index_cut != -1 && min_index_not != -1 && fabs(min_rad_cut-min_rad_not) < EPS){

					tmp_next = min_index_cut;
				}else{

					if(min_rad_cut < min_rad_not){

						tmp_next = min_index_cut;

					}else{

						tmp_next = min_index_not;
					}
				}

			}else{

				tmp_next = (tmp_index+1)%work_P.size();
			}

			if(tmp_next == i)break;

			pre = tmp_index;
			tmp_index = tmp_next;
		}

		COUNT++;
		ret = max(ret,calc_S(work_poly));
	}

	if(COUNT == 0){

		return BIG_NUM;
	}

	return ret;
}


void func(){

	P.clear();
	num_point = 0;

	long double Vx,Vy;
	scanf("%Lf %Lf",&Vx,&Vy);

	long double SLOPE = calc_slope(Line(Point(0,0),Point(Vx,Vy)));

	for(int i = 0; i < N; i++){

		scanf("%Lf %Lf",&point[i].x,&point[i].y);
		num_point++;
	}
	for(int i = 0; i < N; i++){

		P.push_back(i);
	}

	vector<VALUE> V;

	//各点を通る、直線の切片またはX座標(傾きが垂直な場合)を求める
	for(int i = 0; i < num_point; i++){
		if(fabs(SLOPE-DBL_MAX) < EPS){

			V.push_back(VALUE(point[i].x));
		}else{


			V.push_back(VALUE(point[i].y-SLOPE*point[i].x));
		}
	}

	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());

	long double ans = BIG_NUM;

	for(int i = 1; i < V.size(); i++){

		long double L = V[i-1].value,R = V[i].value;

		for(int loop = 0; loop < 100; loop++){

			long double mid1 = (2.0*L+R)/3.0;
			long double mid2 = (1.0*L+2.0*R)/3.0;

			long double S1 = calc_max_S(SLOPE,mid1);
			long double S2 = calc_max_S(SLOPE,mid2);

			ans = min(ans,min(S1,S2));

			if(S1 <= S2){

				R = mid2;
			}else{

				L = mid1;
			}

			if(fabs(R-L) < EPS2)break;
		}
	}

	printf("%.10Lf\n",ans);
}


int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 5020
memory_kb: 3376
final_rank: 19

code_snippet: #include<bits/stdc++.h>
#define inf 1<<29
#define linf 1e10L
#define eps (1e-11L)
#define Eps (1e-7L)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0L+sqrtl(5.0L))/2.0L
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10Lf\n",(ld)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<Eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,ld> pid;
typedef pair<ld,int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpi;

class Point{
public:
  ld x,y;
  Point(ld x=0.0L,ld y=0.0L):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(ld k){ return Point(x*k,y*k);}
  Point operator/(ld k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ 
    return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  ld abs(){ return sqrtl(norm());}
  ld norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

ld norm(Vector a){ return (a.x*a.x+a.y*a.y);}
ld abs(Vector a){ return sqrtl(norm(a));}
ld dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
ld cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  ld r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0L);
}

Point getCrossPointLL(Line a,Line b){
  ld A=cross(a.p2-a.p1,b.p2-b.p1);
  ld B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

ld getDistanceLP(Line l,Point p){
  return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

bool onLine(Line L,Point p){ return getDistanceLP(L,p)<eps; }

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(!onLine(Line(p0,p1),p2))return (cross(a,b)>eps ? 1:-1);
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

bool onSegment(Segment s,Point p){
  if(!onLine(s,p))return false;
  if(dot(s.p2-s.p1,p-s.p1)<-eps)return false;
  if(dot(s.p1-s.p2,p-s.p2)<-eps)return false;
  return true;
}

ld getPolygonArea(Polygon p){
  ld area=0.0L;
  int n=p.size();
  for(int i=0;i<n;i++)area+=cross(p[i%n],p[(i+1)%n]);
  return area/2.0L;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    Segment s(g[i],g[(i+1)%n]);
    if(onSegment(s,p))return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

vector<Polygon> Polygon_cut(Polygon p,Line L){
  vector<Polygon> res;
  vector<vector<int> > g;
  vector<Point> v;
  int n=p.size();
  int ver[p.size()*2];
  fill(ver,ver+p.size()*2,-1);
  for(int i=0;i<n;i++){
    int j=(i+1)%n;
    if(ccw(L.p1,L.p2,p[i])!=-1){
      v.push_back(p[i]);
      ver[v.size()-1]=i;
    }
    Segment s(p[i],p[j]);
    if(isParallel(L,s))continue;
    Point m=getCrossPointLL(s,L);
    if(dot(s.p2-s.p1,m-s.p1)<eps || dot(s.p1-s.p2,m-s.p2)<eps)continue;
    v.push_back(m);
  }

  g.resize(v.size());
  bool onL[v.size()];
  fill(onL,onL+v.size(),false);
  FOR(i,0,v.size())onL[i]=onLine(L,v[i]);
  FOR(i,0,v.size()){
    int j=(i+1)%v.size();
    if(ver[i]+ver[j]==-2)continue;
    if(ver[i]!=-1 && ver[j]!=-1){
      if((ver[i]+1)%n!=ver[j])continue;
      if(onL[i] && onL[j] && dot(L.p2-L.p1,v[j]-v[i])<-eps)continue;
    }
    else if(onL[i] && onL[j])continue;
    g[i].push_back(j);
  }
  
  vector<pair<ld,int> > list;
  for(int i=0;i<v.size();i++)
    if(onLine(L,v[i]))
      list.push_back(make_pair(dot(L.p2-L.p1,v[i]-L.p1),i));
  sort(list.begin(),list.end());
  for(int i=1;i<list.size();i++){
    int a=list[i-1].s,b=list[i].s;
    if(contains(p,v[a]+(v[b]-v[a])/2.0L)==2)g[a].push_back(b);
  }

  reverse(list.begin(),list.end());
  bool used[v.size()];
  fill(used,used+v.size(),false);

  for(int i=0;i<list.size();i++){
    int s=list[i].s,a=-1;
    for(int j=0;j<g[s].size();j++){
      if(used[g[s][j]])continue;
      a=g[s][j];
    }
    if(a==-1)continue;
    Polygon P;

    while(1){
      P.push_back(v[a]);
      if(onL[a] && used[a])break;
      used[a]=true;
      if(a==s)break;
      int b=-1;
      for(int j=0;j<g[a].size();j++){
        b=g[a][j];
        if(onL[b])break;
      }
      if(b==-1){ P.clear();break; }
      a=b;
    }
    if(getPolygonArea(P)>eps)res.push_back(P);
  }
  
  return res;
}

int n;
Vector v,rv;
Polygon p;

ld cal(Point a){
  ld res=-linf;
  vector<Polygon> vp;
  vp=Polygon_cut(p,Line(a,a+v));
  FOR(i,0,vp.size())res=max(res,getPolygonArea(vp[i]));
  vp=Polygon_cut(p,Line(a+v,a));
  FOR(i,0,vp.size())res=max(res,getPolygonArea(vp[i]));
  if(res==-linf)return linf;
  return res;
}

bool comp(Point a,Point b){ return dot(rv,a)<dot(rv,b); }

ld solve(){
  ld res=linf;
  vector<Point> vp;
  rv.x=-v.y;
  rv.y=v.x;
  FOR(i,0,n)vp.pb(project(Line(Point(),rv),p[i]));
  sort(all(vp),comp);
  FOR(i,1,n){
    Point a=vp[i-1],b=vp[i];
    Vector V=(b-a);
    if(abs(V)<Eps)continue;
    V=V/abs(V);
    ld L=0.0L,R=abs(b-a);
    FOR(k,0,50){
      ld m1=(L*phi+R)/(phi+1.0L);
      ld m2=(L+R*phi)/(phi+1.0L);
      ld res1=cal(a+V*m1);
      ld res2=cal(a+V*m2);
      if(res1<res2)R=m2;
      else L=m1;
      if(equals(L,R))break;
    }
    res=min(res,cal(a+V*L));
  }  
  return res;
}

int main()
{
  while(cin>>n && n){
    cin>>v.x>>v.y;
    p.resize(n);
    FOR(i,0,n)cin>>p[i].x>>p[i].y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 7670
memory_kb: 3304
final_rank: 20

code_snippet: #include<cstdio>
#include<complex>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<iostream>
#include<cassert>
#include<algorithm>

using namespace std;

typedef double Real;
typedef complex<Real> Point;
typedef pair<Point,Point> Line;
typedef pair<Point,Point> Segment;
typedef vector<Point> Polygon;

const Real eps=1e-7;
const Real eps2=5e-7;
const Real PI=acos(-1.0);
const Point NPoint=Point(NAN,NAN);
const Real inf=1e9;

int cnt=0;

template<class T> bool eq(T a, T b){
	return abs(a-b)<eps;
}

template<class T> int sgn(T a){
	if(eq(a,(T)0)) return 0;
	if(a>0) return 1;
	return -1;
}

void print(Point p,char ch='\n'){
	printf("(%f %f)%c",p.real(),p.imag(),ch);
}

void print(Polygon poly){
	printf("----\n");
	for(int i=0;i<poly.size();i++){
		print(poly[i]);
	}
	printf("----\n");
}

Polygon poly;
Point vec;
vector<Real> xs;

Real doP(Point a,Point b){
	return (conj(a)*b).real();
}

Real crP(Point a,Point b){
	return (conj(a)*b).imag();
}

bool onSeg(Point p,Point q,Point r){
	return eq(abs(p-q),abs(p-r)+abs(r-q));
}

Point toVec(Line l){
	return l.second-l.first;
}

bool isPara_(Line l1,Line l2){
	return eq(crP(toVec(l1),toVec(l2)),(Real)0);
}

Real getArea(Polygon poly){
	Real res=0;
	for(int i=0;i+1<poly.size();i++){
		res+=crP(poly[i],poly[i+1])/2;
	}
	res=abs(res);
	return res;
}

void rot(){
	Point p=Point(0,1);
	vec/=abs(vec);
	Point m=p/vec;
	for(int i=0;i<poly.size();i++){
		poly[i]*=m;
	}
	vector<Real> tmp;
	for(int i=0;i+1<poly.size();i++){
		bool ok=true;
		for(int j=0;j<tmp.size();j++){
			if(eq(tmp[j],poly[i].real())) ok=false;
		}
		if(ok) tmp.push_back(poly[i].real());
	}
	for(int i=0;i<poly.size();i++){
		for(int j=0;j<tmp.size();j++){
			if(eq(poly[i].real(),tmp[j])){
				poly[i]=Point(tmp[j],poly[i].imag());
				break;
			}
		}
	}
	xs=tmp;
	sort(xs.begin(),xs.end());
}

Point cmp_c;
bool cmp_ang(const Point &p1,const Point &p2){
	return arg(p1-cmp_c)<arg(p2-cmp_c);
}

struct PLexCmp{
	bool operator()(const Point &p1,const Point &p2) const {
		if(p1.real()!=p2.real()) return p1.real()<p2.real();
		return p1.imag()<p2.imag();
	}
};

struct SegLexCmp{
	bool operator()(const Segment &s1,const Segment &s2) const {
		if(s1.first.real()!=s2.first.real()) return s1.first.real()<s2.first.real();
		if(s1.first.imag()!=s2.first.imag()) return s1.first.imag()<s2.first.imag();
		if(s1.second.real()!=s2.second.real()) return s1.second.real()<s2.second.real();
		return s1.second.imag()<s2.second.imag();
	}
};

map<Point,vector<Point>,PLexCmp> con_pts;
vector<Real> ys;
set<Segment,SegLexCmp> invalid_es;

bool genConPts(Real x){
	map<Point,vector<Point>,PLexCmp> emptyMap;
	swap(emptyMap,con_pts);
	ys.clear();
	set<Segment,SegLexCmp> emptySet;
	swap(invalid_es,emptySet);
	for(int i=0;i+1<poly.size();i++){
		Point p=poly[i],q=poly[i+1];
		if(p.real()==x){
			ys.push_back(p.imag());
		}
	//	bool swapped=false;
		if(p.real()>q.real()){
	//		swapped=true;
			swap(p,q);
		}
		if(q.real()<=x||p.real()>=x){
			con_pts[p].push_back(q);
			con_pts[q].push_back(p);
			invalid_es.insert(Segment(poly[i+1],poly[i]));
			continue;
		}
		Real y=p.imag()+((q.imag()-p.imag())*(x-p.real())/(q.real()-p.real()));
		if(y==p.imag()){
			if(p.imag()>q.imag()) y+=eps;
			else y-=eps;
		}
		ys.push_back(y);
		Point r=Point(x,y);
		con_pts[p].push_back(r);
		con_pts[r].push_back(p);
		con_pts[q].push_back(r);
		con_pts[r].push_back(q);
		invalid_es.insert(Segment(poly[i+1],r));
		invalid_es.insert(Segment(r,poly[i]));
	}
	sort(ys.begin(),ys.end());
	int ln=ys.size();
	ys.erase(unique(ys.begin(),ys.end()),ys.end());
	if(ln!=ys.size()) return false;
	for(int i=0;i+1<ys.size();i++){
		Point p=Point(x,ys[i]);
		Point q=Point(x,ys[i+1]);
		con_pts[p].push_back(q);
		con_pts[q].push_back(p);
	}
	map<Point,vector<Point>,PLexCmp> :: iterator it=con_pts.begin();
	for(;it!=con_pts.end();it++){
		vector<Point> &vec=it->second;
		cmp_c=it->first;
		sort(vec.begin(),vec.end(),cmp_ang);
		vec.erase(unique(vec.begin(),vec.end()),vec.end());
	/*	vector<Point> vec2;
		for(int i=0;i<vec.size();i++){
			if(i==0||(vec[i].real()!=vec[i-1].real()||vec[i].imag()!=vec[i-1].imag())){
				vec2.push_back(vec[i]);
			}
		}
		vec=vec2;*/
	}
	for(it=con_pts.begin();it!=con_pts.end();it++){
		for(int i=0;i<(it->second).size();i++){
			Point p=(it->second)[i];
			assert(con_pts.find(p)!=con_pts.end());
		}
	}
	return true;
}

void stroke(vector<Point> &vec,Point cur,Point prv,Point ini){
	vector<Point> pts=con_pts[cur];
	cmp_c=cur;
	int id=distance(pts.begin(),lower_bound(pts.begin(),pts.end(),prv,cmp_ang));
	assert(prv==pts[id]);
	id--;
	if(id==-1) id=pts.size()-1;
	assert(0<=id&&id<pts.size());
	Point nxt=pts[id];
	vec.push_back(nxt);
	if(nxt==ini) return;
	stroke(vec,nxt,cur,ini);
}

int whichSide(Polygon poly,Real x){
	bool le=false,ri=false;
	for(int i=0;i<poly.size();i++){
		if(poly[i].real()<x) le=true;
		if(poly[i].real()>x) ri=true;
	}
	if(le&&ri) return 0;
	else if(le) return -1;
	else if(ri) return 1;
	printf("error whichSide\n");
	printf("%f\n",x);
	print(poly);
	for(int i=0;i<ys.size();i++){
		printf("%f\n",ys[i]);
	}
	vector<Point> vec=con_pts[poly[0]];
	print(poly[0]);
	for(int i=0;i<vec.size();i++){
		printf("-");
		print(vec[i]);
	}
	printf("\n\n\n");
	map<Point,vector<Point>,PLexCmp> ::iterator it=con_pts.begin();
	for(;it!=con_pts.end();it++){
		print(it->first);
		for(int i=0;i<(it->second).size();i++){
			printf("-");
			print((it->second)[i]);
		}
	}
	exit(0);
}

bool isValid_(Polygon poly){
	for(int i=0;i+1<poly.size();i++){
		Segment seg=Segment(poly[i],poly[i+1]);
		if(invalid_es.find(seg)!=invalid_es.end()) return false;
	}
	return true;
}

pair<Real,Real> calcArea(Real x){
	Real le=0,ri=0;
	bool flg=genConPts(x);
	if(flg==false){
		return make_pair(inf,inf);
	}
	if(ys.size()<=1){
		return make_pair(inf,inf);
	}/*
	for(map<Point,vector<Point>,PLexCmp>::iterator it=con_pts.begin();it!=con_pts.end();it++){
		print(it->first,':');
		vector<Point> vec=it->second;
		for(int i=0;i<vec.size();i++){
			print(vec[i]);
		}
	}*/
	for(int i=0;i+1<ys.size();i++){
		Point p=Point(x,ys[i]);
		Point q=Point(x,ys[i+1]);
		vector<Point> poly;
		stroke(poly,p,q,p);
		poly.push_back(poly[0]);
		//bool flg=isRight(poly,x);
		int side=whichSide(poly,x);
		Real area=getArea(poly);/*
		if(flg) ri=max(ri,area);
		else {}//le=max(le,area);*/
		bool flg=isValid_(poly);
		if(side==1&&flg) ri=max(ri,area);
		//print(poly);
		
		poly.clear();
		stroke(poly,q,p,q);
		poly.push_back(poly[0]);
		//print(poly);
		//flg=isRight(poly,x);
		side=whichSide(poly,x);
		area=getArea(poly);/*
		if(flg) {}//ri=max(ri,area);
		else le=max(le,area);*/
		flg=isValid_(poly);
		if(side==-1&&flg) le=max(le,area);
	}
	return make_pair(le,ri);
}

Real calcEdgeCase(){
	Real res=getArea(poly);
	for(int i=1;i+1<xs.size();i++){
		pair<Real,Real> p=calcArea(xs[i]);
	//	printf("%f %f %f\n",xs[i],p.first,p.second);
		res=min(res,max(p.first,p.second));
	}
	return res;
}

Real calc(Real lb,Real ub,Real cur_best){
	Real res=inf;
	pair<Real,Real> p1,p2;
	p1=calcArea(lb);
	p2=calcArea(ub);
//	printf("a%f %f %f\n",lb,ub,cur_best);
	if(lb>ub) return cur_best;
	//if(max(p1.first,p1.second)>cur_best||max(p2.first,p2.second)>cur_best) return cur_best;
	if(p1.first>p1.second) return min(cur_best,p1.first);
	if(p2.first<p2.second) return min(cur_best,p2.second);
	for(int stage=0;stage<100;stage++){
		Real mid=(ub+lb)/2;
		pair<Real,Real> p=calcArea(mid);
		if(p.first>0&&p.second>0){
			res=min(res,max(p.first,p.second));
		}
		if(p.first==0||p.second==0){
			if(stage<50){
				Real tmp=cur_best;
				Real a=calc(lb+eps,mid-eps,tmp);
				tmp=min(tmp,a);
				a=calc(mid+eps,ub-eps,tmp);
				tmp=min(tmp,a);
				return tmp;
			}
		}
	//	printf("%f %f %f\n",mid,p.first,p.second);
		if(p.first<p.second){
			lb=mid;
		}else{
			ub=mid;
		}
	}
	return res;
}

Real solve(){
	rot();
	Real res=calcEdgeCase();
	//printf("edge case best = %f\n",res);
/*	for(int i=0;i+1<xs.size();i++){
		Real lb=xs[i]+eps2,ub=xs[i+1]-eps2;
		Real tmp=calc(lb,ub,res);
		res=min(res,tmp);
	}*/
	Real l=inf,r=-inf;
	vector<Real> xs;
	for(int i=0;i+1<poly.size();i++){
		l=min(l,poly[i].real());
		r=max(r,poly[i].real());
		Point p=poly[i],q=poly[i+1],r=poly[i+2>=poly.size()?0:i+2];
		if(crP(p-q,r-q)>0){
			if(p.real()==q.real()||q.real()==r.real()) continue;
			if(p.real()<q.real()!=q.real()<r.real()){
				xs.push_back(q.real());
			}
		}
	}
	xs.push_back(l);
	xs.push_back(r);
	sort(xs.begin(),xs.end());
	for(int i=0;i+1<xs.size();i++){
		Real lb=xs[i]+eps2,ub=xs[i+1]-eps2;
		Real tmp=calc(lb,ub,res);
		res=min(res,tmp);
	}
	return res;
}

void init(){
	poly.clear();
	xs.clear();
	ys.clear();
	map<Point,vector<Point>,PLexCmp> tmp;
	swap(con_pts,tmp);
}

void input(){
	int N;
	scanf("%d",&N);
	if(N==0) exit(0);
	int x,y;
	scanf("%d%d",&x,&y);
	vec=Point(x,y);
	for(int i=0;i<N;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		poly.push_back(Point(x,y));
	}
	poly.push_back(poly[0]);
	cnt++;
}

int main(){
	while(true){
		init();
		input();
		Real ans=solve();
		printf("%f\n",ans);
//		cout<<ans<<"\n";
//		break;
	}
	return 0;
}
accuracy: 1
time_ms: 1470
memory_kb: 1496
final_rank: 3

code_snippet: #include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
const long double EPS = 1e-15;
const long double INF = 1e+10;
const long double PI = acos(-1);
int sig(long double r) { return (r < -EPS) ? -1 : (r > +EPS) ? +1 : 0; }
inline long double ABS(long double a){return max(a,-a);}
struct Pt {
	long double x, y;
	Pt() {}
	Pt(long double x, long double y) : x(x), y(y) {}
	Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
	Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
	Pt operator*(const Pt &a) const { return Pt(x * a.x - y * a.y, x * a.y + y * a.x); }
	Pt operator-() const { return Pt(-x, -y); }
	Pt operator*(const long double &k) const { return Pt(x * k, y * k); }
	Pt operator/(const long double &k) const { return Pt(x / k, y / k); }
	long double ABS() const { return sqrt(x * x + y * y); }
	long double abs2() const { return x * x + y * y; }
	long double arg() const { return atan2(y, x); }
	long double dot(const Pt &a) const { return x * a.x + y * a.y; }
	long double det(const Pt &a) const { return x * a.y - y * a.x; }
};
long double tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }
int iSP(Pt a, Pt b, Pt c) {
	int s = sig((b - a).det(c - a));
	if (s) return s;
	if (sig((b - a).dot(c - a)) < 0) return -2; // c-a-b
	if (sig((a - b).dot(c - b)) < 0) return +2; // a-b-c
	return 0;
}
int iLL(Pt a, Pt b, Pt c, Pt d) {
	if (sig((b - a).det(d - c))) return 1; // intersect
	if (sig((b - a).det(c - a))) return 0; // parallel
	return -1; // correspond
}
bool iLS(Pt a, Pt b, Pt c, Pt d) {
	return (sig(tri(a, b, c)) * sig(tri(a, b, d)) <= 0);
}
bool iSS(Pt a, Pt b, Pt c, Pt d) {
	return (iSP(a, b, c) * iSP(a, b, d) <= 0 && iSP(c, d, a) * iSP(c, d, b) <= 0);
}
bool iSSstrict(Pt a, Pt b, Pt c, Pt d) {
	return (sig(tri(a, b, c)) * sig(tri(a, b, d)) < 0 && sig(tri(c, d, a)) * sig(tri(c, d, b)) < 0);
}
Pt pLL(Pt a, Pt b, Pt c, Pt d) {
	b = b - a; d = d - c; return a + b * (c - a).det(d) / b.det(d);
}


Pt p[110];
Pt v;
int n;
long double z[110];
pair<long double,int>ev[110];
int vis[110];
int to[110];
long double tx[110];
long double fx[110];

long double calc2(long double y,int d){
	long double ret=0;
	int now=0;
	int sz=0;
	for(int i=0;i<n;i++){
		if(iLS(Pt(0,y),Pt(1,y),p[i],p[i+1])){
			ev[sz++]=make_pair(pLL(Pt(0,y),Pt(1,y),p[i],p[i+1]).x,i);
		}
	}
	for(int i=0;i<n;i++)to[i]=-1;
	std::sort(ev,ev+sz);
	//printf("%d\n",sz);
	for(int i=0;i<sz;i++){
		to[ev[i].second]=ev[i^1].second;
		tx[ev[i].second]=ev[i^1].first;
		fx[ev[i].second]=ev[i].first;
	}
	for(int i=0;i<n;i++)vis[i]=0;
	for(int i=0;i<n;i++){
		if(vis[i])continue;
		if(d==0&&p[i].y>y)continue;
		if(d==1&&p[i].y<y)continue;
		long double val=0;
		int at=i;
		Pt pos=p[i];
		bool fl=true;
		while(1){
			if(fl)vis[at]=1;
			if(fl&&~to[at]){
				fl=false;
				val+=pos.det(Pt(fx[at],y));
				val+=(Pt(fx[at],y)).det(Pt(Pt(tx[at],y)));
				pos=Pt(tx[at],y);
				at=to[at];
			}else{
				fl=true;
				val+=pos.det(p[at+1]);
				at=(at+1)%n;
				pos=p[at];
			}
			if(fl&&vis[at])break;
		}
		if(val<0)val=-val;
//		if(val<0)printf("%Lf\n",val);
		ret=max(ret,val/2);
	}
	//if(ret<1)printf("%Lf %d: %Lf\n",y,d,ret);
	return ret;
}
long double calc(long double y){
	return max(calc2(y-EPS*10000,0),calc2(y+EPS*10000,1));
}
int main(){
	int a;
	while(scanf("%d",&a),a){
		n=a;
		for(int i=0;i<110;i++)p[i]=Pt(0,0);
		v=Pt(0,0);
		long double X,Y;
		scanf("%Lf%Lf",&X,&Y);
		v=Pt(X,Y);
		long double th=v.arg();
		for(int i=0;i<a;i++){
			scanf("%Lf%Lf",&X,&Y);
			p[i]=Pt(X,Y);
			p[i]=p[i]*Pt(cos(th),-sin(th));
			z[i]=p[i].y;
		//	printf("%Lf %Lf\n",p[i].x,p[i].y);
		}
		
		p[a]=p[0];
		std::sort(z,z+a);
		long double ret=999999999;
		for(int i=0;i<a;i++){
			if(i==0||sig(z[i]-z[i-1])==0)continue;
			ret=min(ret,calc(z[i]));

			long double left=z[i-1];
			long double right=z[i];
			for(int j=0;j<100;j++){
				long double M1=calc((left*2+right)/3);
				long double M2=calc((left+right*2)/3);
				ret=min(ret,min(M1,M2));
				if(M1>M2)left=(left*2+right)/3;
				else right=(right*2+left)/3;
			}
		}
		printf("%.12Lf\n",ret);
	}
}
accuracy: 1
time_ms: 1320
memory_kb: 1188
final_rank: 1

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef long double R;
	const R INF = 1e8;
	R EPS = 1e-15;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2;	// s-t-p
		return 0;								// s-p-t
	}
	
	
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			// 座標の二乗とEPSの差が大きすぎないように注意
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > EPS && inp(p-at(1), -dir()) > -EPS;
			//return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
		BOOL contains(const P &p)const {
			R sum = .0;
			REP(i, size()){
				if(S(at(i), at((i+1)%size())).online(p)) return BORDER;	// online
				sum += arg((at(i) - p) / (at((i+1)%size()) - p));
			}
			return !!sig(sum);
		}
		R area()const {
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
	};

	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
	inline P reflect(const P &s, const L &t){return (R)2.*proj(s, t) - s;}
	inline S reflect(const S &s, const L &t){return S(reflect(s[0], t), reflect(s[1], t));}
	BOOL intersect(const S &s, const S &t){
		const int p = ccw(t[0], t[1], s[0], 1) * ccw(t[0], t[1], s[1], 1);
		const int q = ccw(s[0], s[1], t[0], 1) * ccw(s[0], s[1], t[1], 1);
		return (p>0||q>0) ? FALSE : (!p||!q) ? BORDER : TRUE;
	}
	BOOL intersect(const S &s, const L &l){
		if(l.online(s[0]) || l.online(s[1])) return BORDER;
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
		return m[0] + B / A * (m[1] - m[0]);
	}
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		vector<G> poly;
		
		void add_polygon(int s, int t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			e->l = t;
			poly[t].push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		
		vector<G>& dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			poly.emplace_back();
			add_polygon(s, poly.size()-1, -PI*(R).5);
			REP(i, n)REP(j, g[i].size())if(!g[i][j].f){
				poly.emplace_back();
				add_polygon(i, poly.size()-1, g[i][j].a+2.*EPS);
			}
			return poly;
		}
	};
	template<class Func> R simpson(R s, R t, Func func){
		return (t-s)/6*(func(s+2*EPS) + func(t-2*EPS) + 4*func((s+t)*(R).5));
	}

#undef SELF
#undef at
}

using namespace geom;

int f = 0;
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
	istream& operator>>(istream &is, L &l){l.resize(2);return is >> l[0] >> l[1];}
}

int n;
G g;
R minarea(R x, int f = 0){
	vector<P> p = g;
	L xl(P(x, 0), P(x, 1));
	vector<pair<P, int>> ip;
	vector<pii> segs;
	REP(i, n){
		const S &s = g.edge(i);
		if(sig(s.dir().X) && intersect(s, xl)){
			P cp = crosspoint(s, xl);
			if(!sig(norm(cp-s[0]))) ip.emplace_back(s[0], i);
			else if(!sig(norm(cp-s[1]))) ip.emplace_back(s[1], (i+1)%n);
			else{
				segs.emplace_back(i, p.size());
				segs.emplace_back(p.size(), (i+1)%n);
				ip.emplace_back(cp, p.size());
				p.push_back(cp);
				continue;
			}
		}
		segs.emplace_back(i, (i+1)%n);
	}
	sort(ALL(ip));
	REP(i, (int)ip.size()-1){
		if(ip[i].second != ip[i+1].second && g.contains((ip[i].first + ip[i+1].first) * (R).5))
			segs.emplace_back(ip[i].second, ip[i+1].second);
	}
	DualGraph dg(p);
	FOR(it, segs) dg.add_edge(it->first, it->second);
	const vector<G> &poly = dg.dual();
	R ans = .0;
	REPS(i, (int)poly.size()-1) ans = max(ans, poly[i].area());
	return ans;
}

int main(int argc, char *argv[]){
	ios::sync_with_stdio(false);
	while(cin >> n, n){
		P v;
		g.resize(n);
		cin >> v; v = unit(v);
		vector<R> x;
		REP(i, n){
			cin >> g[i];
			g[i] *= P(0, 1) / v;
			x.push_back(g[i].X);
		}
		sort(ALL(x)); UNIQUE(x);
		R ans = INF, ansx = .0;
		REP(i, (int)x.size() - 1){
			ans = min(ans, minarea(x[i]));
			if(minarea(x[i]) < minarea(x[i]+1e-5) || minarea(x[i+1]) < minarea(x[i+1]-1e-5)) continue;
			R l = x[i], r = x[i+1];
			while(r-l > 1e-6){
				R ml = minarea((2*l+r)/3);
				R mr = minarea((l+2*r)/3);
				ans = min(ans, ml);
				ans = min(ans, mr);
				if(ml < mr) r = (l+2*r)/3;
				else l = (2*l+r)/3;
			}
		}
		printf("%.10f\n", (double)ans);
	}
	return 0;
}
accuracy: 1
time_ms: 1290
memory_kb: 1420
final_rank: 2