点,线,面,形基本关系,点积叉积的理解
poj2318 TOYS
/****************************\ * @prob: poj2318 TOYS * * @auth: Wang Junji * * @stat: Accepted. * * @date: June. 25th, 2012 * * @memo: 点和直线位置关系 * \****************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> const int maxN = 5010; int cnt[maxN], lower[maxN], upper[maxN], n, m, X0, Y0, X1, Y1; inline int Find(int x, int y) { int L = 0, R = n; while (L < R) { int Mid = (L + R) >> 1; double __x = (upper[Mid] - lower[Mid]) / double(Y1 - Y0) * (y - Y0) + lower[Mid]; if (__x < x) L = Mid + 1; else R = Mid; } /* while */ return R - 1; } /* Find */ int main() { freopen("toys.in" , "r", stdin ); freopen("toys.out", "w", stdout); while (~scanf("%d%d%d%d%d%d", &n, &m, &X0, &Y1, &X1, &Y0) && n) { ++n; upper[0] = lower[0] = X0; for (int i = 1; i < n; ++i) scanf("%d%d", upper + i, lower + i); lower[n] = upper[n] = X1; memset(cnt, 0, sizeof cnt); while (m--) { int x, y; scanf("%d%d", &x, &y); ++cnt[Find(x, y)]; } /* while */ for (int i = 0; i < n; ++i) printf("%d: %d\n", i, cnt[i]); puts(""); } /* while */ return 0; } /* main */ /* 用二分查找每个玩具所对应的分区即可。 */poj2398 Toy Storage
/*******************************\ * @prob: poj2398 Toy Storage * * @auth: Wang Junji * * @stat: Accepted. * * @date: June. 25th, 2012 * * @memo: 点和直线位置关系 * \*******************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> const int maxN = 1010; int has[maxN], cnt[maxN], lower[maxN], upper[maxN], n, m, X0, Y0, X1, Y1; inline int Find(int x, int y) { int L = 0, R = n; while (L < R) { int Mid = (L + R) >> 1; double __x = (upper[Mid] - lower[Mid]) / double(Y1 - Y0) * (y - Y0) + lower[Mid]; if (__x < x) L = Mid + 1; else R = Mid; } /* while */ return R - 1; } /* Find */ int main() { freopen("Toy_Storage.in" , "r", stdin ); freopen("Toy_Storage.out", "w", stdout); while (~scanf("%d%d%d%d%d%d", &n, &m, &X0, &Y1, &X1, &Y0) && n) { ++n; upper[0] = lower[0] = X0; for (int i = 1; i < n; ++i) scanf("%d%d", upper + i, lower + i); lower[n] = upper[n] = X1; std::sort(lower, lower + n); std::sort(upper, upper + n); memset(cnt, 0, sizeof cnt); memset(has, 0, sizeof has); while (m--) { int x, y; scanf("%d%d", &x, &y); ++has[Find(x, y)]; } /* while */ puts("Box"); for (int i = 0; i < n; ++i) ++cnt[has[i]]; for (int i = 1; i < n; ++i) if (cnt[i]) printf("%d: %d\n", i, cnt[i]); } /* while */ return 0; } /* main */ /* 用二分查找每个玩具所对应的分区即可。 */视野动态规划
poj1556 The Doors
/*****************************\ * @prob: poj1556 The Doors * * @auth: Wang Junji * * @stat: Accepted. * * @date: June. 25th. 2012 * * @memo: 视野动态规划 * \*****************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> #include <cmath> const int maxN = 110; const double INF = 1e198, zero = 1e-8; struct vec { double x, y; vec() {} /* vec */ vec(const double& x, const double& y): x(x), y(y) {} /* vec */ vec(const vec& b): x(b.x), y(b.y) {} /* vec */ vec operator-(const vec& b) const {return vec(x - b.x, y - b.y);} /* operator- */ double operator*(const vec& b) const {return x * b.y - y * b.x;} /* operator* */ vec lwr() const {return vec(x, y - 1);} /* lwr */ vec upr() const {return vec(x, y + 1);} /* upr */ } p[maxN][4]; int n; double d[maxN][4]; template <typename _Tp> inline _Tp& gmax(_Tp& a, const _Tp& b) {return a > b ? a : (a = b);} /* gmax */ template <typename _Tp> inline _Tp& gmin(_Tp& a, const _Tp& b) {return a < b ? a : (a = b);} /* gmin */ template <typename _Tp> inline _Tp sqr(const _Tp& x) {return x * x;} /* sqr */ inline bool check(const vec& lwr, const vec& upr, const vec& st , const vec& ed) { if (st.x - ed.x > -zero) return false; if ((ed - st) * (lwr - st) > zero) return false; if ((upr - st) * (ed - st) > zero) return false; return true; } /* check */ inline double dist(const vec& a, const vec& b) {return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));} /* dist */ inline void work(const double& val, const vec& lwr, const vec& upr, const vec& st, const int& i) { if (val - INF > -zero) return; if (d[n][0] - 10 < zero) return; if (i == n && check(lwr, upr, st, p[n][0])) gmin(d[n][0], val + dist(st, p[n][0])); for (int j = 0; j < 4; ++j) if (check(lwr, upr, st, p[i][j])) gmin(d[i][j], val + dist(st, p[i][j])); vec __lwr(lwr), __upr(upr); bool ch_lwr = check(lwr, upr, st, p[i][0]), ch_upr = check(lwr, upr, st, p[i][1]); if (ch_lwr) __lwr = p[i][0]; if (ch_upr) __upr = p[i][1]; if (__lwr * __upr > zero && (ch_lwr || ch_upr)) work(val, __lwr, __upr, st, i + 1); __lwr = lwr, __upr = upr; ch_lwr = check(lwr, upr, st, p[i][2]); ch_upr = check(lwr, upr, st, p[i][3]); if (ch_lwr) __lwr = p[i][2]; if (ch_upr) __upr = p[i][3]; if (__lwr * __upr > zero && (ch_lwr || ch_upr)) work(val, __lwr, __upr, st, i + 1); return; } /* work */ int main() { freopen("door.in" , "r", stdin ); freopen("door.out", "w", stdout); while (~scanf("%d", &n) && ~n) { p[0][0] = vec(0., 5.); ++n; for (int i = 1; i < n; ++i) { double x, y0, y1, y2, y3; scanf("%lf%lf%lf%lf%lf", &x, &y0, &y1, &y2, &y3); p[i][0] = vec(x, y0); p[i][1] = vec(x, y1); p[i][2] = vec(x, y2); p[i][3] = vec(x, y3); d[i][0] = d[i][1] = d[i][2] = d[i][3] = INF; } /* for */ p[n][0] = vec(10., 5.); d[n][0] = INF; work(0, p[0][0].lwr(), p[0][0].upr(), p[0][0], 1); for (int i = 1; i < n; ++i) for (int j = 0; j < 4; ++j) work(d[i][j], p[i][j].lwr(), p[i][j].upr(), p[i][j], i + 1); printf("%.2lf\n", d[n][0]); } /* while */ return 0; } /* main */ /* 维护视野的上界和下界,然后依次松弛每个点即可。 */凸包、旋转卡壳
UVa681 Convex Hull Finding
/**************************************\ * @prob: UVa681 Convex Hull Finding * * @auth: Wang Junji * * @stat: Accepted. * * @date: June. 26th, 2012 * * @memo: 凸包 * \**************************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> int const maxN = 520; struct vec { int x, y; vec() {} /* vec */ vec(int x, int y): x(x), y(y) {} /* vec */ vec operator-(const vec& b) const {return vec(x - b.x, y - b.y);} /* operator- */ int operator*(const vec& b) const {return x * b.y - y * b.x; } /* operator- */ } p[maxN], res[maxN]; int n, T; inline vec const* Granham(vec const* const __fir, vec const* const __la, vec* res) { vec* tmp = res + 1; vec const* fir = __fir; if (fir == __la) return res; *res++ = *fir++; if (fir == __la) return res; *res++ = *fir++; if (fir == __la) return res; for (; fir != __la; *res++ = *fir++) while (res != tmp && (fir[0] - res[-1]) * (res[-1] - res[-2]) >= 0) --res; tmp = res; *res++ = __la[-2]; for (fir = __la - 2; fir-- != __fir; *res++ = *fir) while (res != tmp && (fir[0] - res[-1]) * (res[-1] - res[-2]) >= 0) --res; return res; } /* Granham */ inline bool cmp(vec const& a, vec const& b) {return a.y < b.y || (a.y == b.y && a.x < b.x);} /* cmp */ int main() { freopen("Convex_Hull.in" , "r", stdin ); freopen("Convex_Hull.out", "w", stdout); for (scanf("%d", &T), printf("%d\n", T); T--; ~scanf("\n-1") && puts("-1")) { scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%d%d", &p[i].x, &p[i].y); std::sort(p, p + n, cmp); n = Granham(p, p + n, res) - res; printf("%d\n", n); for (int i = 0; i < n; ++i) printf("%d %d\n", res[i].x, res[i].y); } /* for */ return 0; } /* main */ /* 凸包的模板题,不再多说。 */poj2187 Beauty Contest
/**********************************\ * @prob: poj2187 Beauty Contest * * @auth: Wang Junji * * @stat: Accepted. * * @date: June. 28th, 2012 * * @memo: 旋转卡壳 * \**********************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> const int maxN = 50010; struct vec { int x, y; vec() {} /* vec */ vec(int x, int y): x(x), y(y) {} /* vec */ vec operator-(const vec& b) const {return vec(x - b.x, y - b.y);} /* operator- */ int operator*(const vec& b) const {return x * b.y - y * b.x;} /* operator* */ int sqrabs() const {return x * x + y * y;} } p[maxN], res[maxN]; int n; inline int& gmax(int& a, const int& b) {return a > b ? a : (a = b);} /* gmax */ inline bool cmp(const vec& a, const vec& b) {return a.y < b.y || (a.y == b.y && a.x < b.x);} /* cmp */ inline const vec* Granham(const vec* const __fir, const vec* const __la, vec* res) { const vec* fir = __fir; const vec* tmp = res + 1; for (*res++ = *fir++, *res++ = *fir++; fir != __la; *res++ = *fir++) while (res != tmp && (fir[0] - res[-1]) * (res[-1] - res[-2]) >= 0) --res; tmp = res; *res++ = __la[-2]; for (fir = __la - 2; fir-- != __fir; *res++ = *fir) while (res != tmp && (fir[0] - res[-1]) * (res[-1] - res[-2]) >= 0) --res; return res - 1; } /* Granham */ int main() { freopen("Beauty.in" , "r", stdin ); freopen("Beauty.out", "w", stdout); scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%d%d", &p[i].x, &p[i].y); std::sort(p, p + n, cmp); n = Granham(p, p + n, res) - res; int ans = 0; for (const vec *ths = res, *oppo = res + 2; ths != res + n; ++ths) //注意这里oppo必须从res + 2开始枚举,否则错。 { while ((oppo[1] - ths[0]) * (oppo[1] - ths[1]) > (oppo[0] - ths[0]) * (oppo[0] - ths[1])) if (++oppo == res + n) oppo = res; gmax(ans, (*oppo - *ths).sqrabs()); } /* for */ printf("%d\n", ans); return 0; } /* main */ /* 旋转卡壳模板题,不再多说。 */半平面交
poj2451 Uyuw's Concert
/**********************************\ * @prob: poj2451 Uyuw's Concert * * @auth: Wang Junji * * @stat: Accepted. * * @date: June. 26th. 2012 * * @memo: 半平面交 * \**********************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <deque> using std::deque; typedef double DBL; const int maxN = 20010; const DBL zero = 1e-12L; struct vec { DBL x, y; vec() {} /* vec */ vec(DBL x, DBL y): x(x), y(y) {} /* vec */ vec operator-(const vec& b) const {return vec(x - b.x, y - b.y);} /* operator- */ vec operator+(const vec& b) const {return vec(x + b.x, y + b.y);} /* operator+ */ vec operator*(const DBL& t) const {return vec(x * t, y * t);} /* operator* */ DBL operator*(const vec& b) const {return x * b.y - y * b.x;} /* operator* */ } p[maxN]; struct HP { vec A, B; DBL ang; HP() {} /* HP */ HP(const vec& A, const vec& B): A(A), B(B) {ang = atan2(B.y - A.y, B.x - A.x);} /* HP */ } hp[maxN]; int n; inline int sgn(const DBL& x) {return x < -zero ? -1 : x > zero ? 1 : 0;} /* sgn */ inline DBL sqr(const DBL& x) {return x * x;} /* sqr */ inline bool eql(const HP& a, const HP& b) {return !sgn(a.ang - b.ang);} /* eql */ inline bool notin(const vec& P, const HP& a) {return (P - a.B) * (P - a.A) > -zero;} /* notin */ inline int cmp(const void* __a, const void* __b) { const HP &a = *(HP*)__a, &b = *(HP*)__b; int tmp = sgn(a.ang - b.ang); if (tmp) return tmp; return sgn((b.B - a.A) * (b.A - a.A)); } /* cmp */ inline vec cross(const HP& a, const HP& b) { vec AB = a.B - a.A, CD = b.B - b.A, AC = b.A - a.A, AD = b.B - a.A; return a.A + AB * ((AC * AD) / (AB * CD)); } /* cross */ inline const deque <HP>& Half_Plane_Inter(const HP* fir, const HP* la) { static deque <HP> q; q.clear(); for (q.push_back(*fir++), q.push_back(*fir++); fir != la; q.push_back(*fir++)) { while (q.size() > 1 && notin(cross(*(q.end() - 2), q.back()), *fir)) q.pop_back(); while (q.size() > 1 && notin(cross(q.front(), *(q.begin() + 1)), *fir)) q.pop_front(); } /* for */ for (;;) { bool flag = 0; while (q.size() > 2 && notin(cross(*(q.end() - 2), q.back()), q.front())) q.pop_back(), flag = 1; while (q.size() > 2 && notin(cross(q.front(), *(q.begin() + 1)), q.back())) q.pop_front(), flag = 1; if (!flag) break; } /* for */ return q; } /* Half_Plane_Inter */ int main() { freopen("Concert.in" , "r", stdin ); freopen("Concert.out", "w", stdout); scanf("%d", &n); for (int i = 0; i < n; ++i) { DBL x1, y1, x2, y2; scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); hp[i] = HP(vec(x1, y1), vec(x2, y2)); } /* for */ hp[n++] = HP(vec(0 , 0 ), vec(1e4, 0 )); hp[n++] = HP(vec(1e4, 0 ), vec(1e4, 1e4)); hp[n++] = HP(vec(1e4, 1e4), vec(0 , 1e4)); hp[n++] = HP(vec(0 , 1e4), vec(0 , 0 )); qsort(hp, n, sizeof hp[0], cmp); n = std::unique(hp, hp + n, eql) - hp; deque <HP> res = Half_Plane_Inter(hp, hp + n); if (res.size() < 3) printf("0.0\n"); else { n = 0; p[n++] = cross(res.front(), res.back()); for (deque <HP>::const_iterator iter = res.begin(); iter + 1 != res.end(); ++iter) p[n++] = cross(*iter, *(iter + 1)); DBL ans = 0; for (int i = 1; i + 1 < n; ++i) ans += fabs((p[i + 1] - p[0]) * (p[i] - p[0])); printf("%.1lf\n", ans /= 2); } /* else */ return 0; } /* main */ /* 半平面交的模板题。 注意不能使用long double类型,否则超时。 */poj3384 Feng Shui
/*****************************\ * @prob: poj3384 Feng Shui * * @auth: Wang Junji * * @stat: Accepted. * * @date: June. 28th, 2012 * * @memo: 半平面交 * \*****************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> #include <deque> #include <cmath> using std::deque; const int maxN = 210; const double zero = 1e-10; struct vec { double x, y; vec() {} /* vec */ vec(double x, double y): x(x), y(y) {} /* vec */ vec operator-(const vec& b) const {return vec(x - b.x, y - b.y);} /* operator- */ vec operator+(const vec& b) const {return vec(x + b.x, y + b.y);} /* operator+ */ vec operator*(const double& t) const {return vec(x * t, y * t);} /* operator* */ double operator*(const vec& b) const {return x * b.y - y * b.x;} /* operator* */ double abs() const {return sqrt(x * x + y * y);} /* abs */ } p[maxN]; struct HP { vec A, B; double ang; HP() {} /* HP */ HP(const vec& A, const vec& B): A(A), B(B) {ang = atan2(B.y - A.y, B.x - A.x);} /* HP */ void mv(const double& r) { double d = (B - A).abs(), x1 = A.x, x2 = B.x, y1 = A.y, y2 = B.y; A.x += (y1 - y2) * r / d; B.x += (y1 - y2) * r / d; A.y += (x2 - x1) * r / d; B.y += (x2 - x1) * r / d; } /* mv */ } hp[maxN]; double Rad; int n; inline int sgn(const double& x) {return x < -zero ? -1 : x > zero ? 1 : 0;} /* sgn */ inline int cmp(const void* __a, const void* __b) { const HP &a = *(HP*)__a, &b = *(HP*)__b; int tmp = sgn(a.ang - b.ang); if (tmp) return tmp; return sgn((b.B - a.A) * (b.A - a.A)); } /* cmp */ inline bool eql(const HP& a, const HP& b) {return !sgn(a.ang - b.ang);} /* eql */ inline vec cross(const HP& a, const HP& b) { vec AB = a.B - a.A, CD = b.B - b.A, AC = b.A - a.A, AD = b.B - a.A; return a.A + AB * ((AC * AD) / (AB * CD)); } /* cross */ inline bool outof(const vec& P, const HP& a) {return (P - a.B) * (P - a.A) > zero;} /* outof */ //这里不能排除三点共线的情况。 inline const deque <HP>& Half_Plane_Inter(const HP* fir, const HP* la) { static deque <HP> q; q.clear(); for (q.push_back(*fir++), q.push_back(*fir++); fir != la; q.push_back(*fir++)) { while (q.size() > 1 && outof(cross(*(q.end() - 2), q.back()) , *fir)) q.pop_back (); while (q.size() > 1 && outof(cross(q.front(), *(q.begin() + 1)), *fir)) q.pop_front(); } /* for */ for (;;) { bool flag = 0; while (q.size() > 2 && outof(cross(*(q.end() - 2), q.back()) , q.front())) q.pop_back (), flag = 1; while (q.size() > 2 && outof(cross(q.front(), *(q.begin() + 1)), q.back ())) q.pop_front(), flag = 1; if (!flag) break; } /* for */ return q; } /* Half_Plane_Inter */ int main() { freopen("Feng_Shui.in" , "r", stdin ); freopen("Feng_Shui.out", "w", stdout); while (~scanf("%d%lf", &n, &Rad)) { for (int i = 0; i < n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y); p[n] = p[0]; for (int i = 0; i < n; ++i) hp[i] = HP(p[i + 1], p[i]), hp[i].mv(Rad); qsort(hp, n, sizeof hp[0], cmp); n = std::unique(hp, hp + n, eql) - hp; const deque <HP> res = Half_Plane_Inter(hp, hp + n); if (res.size() < 3) { vec tmp = cross(hp[0], hp[1]); printf("%.4lf %.4lf %.4lf %.4lf\n", tmp.x, tmp.y, tmp.x, tmp.y); } /* if */ else { n = 0; for (deque <HP>::const_iterator iter = res.begin(); iter + 1 != res.end(); ++iter) p[n++] = cross(*iter, *(iter + 1)); p[n++] = cross(res.back(), res.front()); p[n] = p[0]; vec p1, p2; double ans = 0; for (int i = 0; i + 1 < n; ++i) for (int j = i + 1; j < n; ++j) { double d = (p[i] - p[j]).abs(); if (d - ans > -zero) ans = d, p1 = p[i], p2 = p[j]; } /* for */ if (p1.x > p2.x) std::swap(p1, p2); printf("%.4lf %.4lf %.4lf %.4lf\n", p1.x, p1.y, p2.x, p2.y); } /* else */ } /* while */ return 0; } /* main */ /* 这道题的Special Judge有点问题,需要注意: 1) 半平面交时不能排除三点共线的情况(这并不是Sepical Judge的问题,因为这样会排除可能的最优解); 2) 求最远点对时只能用枚举的方法,不能旋转卡壳; 3) 输出最后结果时,保证第一个点的横坐标小于第二个点; 4) 枚举最远点对时,若当前值大于等于最大值时更新,而不是大于。 还要注意半平面交为空的情况,这时候应当通过原始边来找到中间的唯一解。 */poj1279 Art Gallery
/*******************************\ * @prob: poj1279 Art Gallery * * @auth: Wang Junji * * @stat: Accepted. * * @date: June. 28th, 2012 * * @memo: 半平面交 * \*******************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <deque> using std::deque; const int maxN = 1510; const double zero = 1e-8; struct vec { double x, y; vec() {} /* vec */ vec(double x, double y): x(x), y(y) {} /* vec */ vec operator-(const vec& b) const {return vec(x - b.x, y - b.y);} /* operator- */ vec operator+(const vec& b) const {return vec(x + b.x, y + b.y);} /* operator+ */ vec operator*(const double& t) const {return vec(x * t, y * t);} /* operator* */ double operator*(const vec& b) const {return x * b.y - y * b.x;} /* operator* */ } p[maxN]; struct HP { vec A, B; double ang; HP() {} /* HP */ HP(const vec& A, const vec& B): A(A), B(B) {ang = atan2(B.y - A.y, B.x - A.x);} /* HP */ } hp[maxN]; int n, T; inline int sgn(const double& x) {return x < -zero ? -1 : x > zero ? 1 : 0;} /* sgn */ inline bool eql(const HP& a, const HP& b) {return !sgn(a.ang - b.ang);} /* eql */ inline int cmp(const void* __a, const void* __b) { const HP &a = *(HP*)__a, &b = *(HP*)__b; int tmp = sgn(a.ang - b.ang); if (tmp) return tmp; return sgn((b.B - a.A) * (b.A - a.A)); } /* cmp */ inline vec cross(const HP& a, const HP& b) { vec AB = a.B - a.A, CD = b.B - b.A, AC = b.A - a.A, AD = b.B - a.A; return a.A + AB * ((AC * AD) / (AB * CD)); } /* cross */ inline bool notin(const vec& P, const HP& a) {return (P - a.B) * (P - a.A) > -zero;} /* notin */ inline const deque <HP>& Half_Plane_Inter(const HP* fir, const HP* la) { static deque <HP> q; q.clear(); for (q.push_back(*fir++), q.push_back(*fir++); fir != la; q.push_back(*fir++)) { while (q.size() > 1 && notin(cross(*(q.end() - 2), q.back()) , *fir)) q.pop_back (); while (q.size() > 1 && notin(cross(q.front(), *(q.begin() + 1)), *fir)) q.pop_front(); } /* for */ for (;;) { bool flag = 0; while (q.size() > 2 && notin(cross(*(q.end() - 2), q.back()) , q.front())) q.pop_back (), flag = 1; while (q.size() > 2 && notin(cross(q.front(), *(q.begin() + 1)), q.back ())) q.pop_front(), flag = 1; if (!flag) break; } /* for */ return q; } /* Half_Plane_Inter */ int main() { freopen("gallery.in" , "r", stdin ); freopen("gallery.out", "w", stdout); for (scanf("%d", &T); T--;) { scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y); p[n] = p[0]; for (int i = 0; i < n; ++i) hp[i] = HP(p[i + 1], p[i]); qsort(hp, n, sizeof hp[0], cmp); n = std::unique(hp, hp + n, eql) - hp; const deque <HP> res = Half_Plane_Inter(hp, hp + n); if (res.size() < 3) printf("0.00\n"); else { n = 0; double ans = 0; for (deque <HP>::const_iterator iter = res.begin(); iter + 1 != res.end(); ++iter) p[n++] = cross(*iter, *(iter + 1)); p[n++] = cross(res.front(), res.back()); for (const vec* ths = p + 1; ths + 1 != p + n; ++ths) ans += fabs((ths[0] - p[0]) * (ths[1] - p[0])); printf("%.2lf\n", ans /= 2); } /* else */ } /* for */ return 0; } /* main */ /* 半平面交模板题,不多说。 */poj3525 Most Distant Point from the Sea
/*********************************************************\ * @prob: poj3525 Most Distant Point from the Sea * * @auth: Wang Junji * @stat: Accepted. * * @date: June. 26th. 2012 * @memo: 半平面交、二分枚举 * \*********************************************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> #include <deque> #include <cmath> using std::deque; const int maxN = 110; const double zero = 1e-10; struct vec { double x, y; vec() {} /* vec */ vec(double x, double y): x(x), y(y) {} /* vec */ vec operator-(const vec& b) const {return vec(x - b.x, y - b.y);} /* operator- */ vec operator+(const vec& b) const {return vec(x + b.x, y + b.y);} /* operator+ */ vec operator*(const double& t) const {return vec(x * t, y * t);} /* operator* */ double operator*(const vec& b) const {return x * b.y - y * b.x;} /* operator* */ double abs() const {return sqrt(x * x + y * y);} /* abs */ } p[maxN]; struct HP { vec A, B; double ang, len; HP() {} /* HP */ HP(const vec& A, const vec& B): A(A), B(B) { ang = atan2(B.y - A.y, B.x - A.x); len = (B - A).abs(); } /* HP */ } hp[maxN], hp1[maxN]; int n; inline int sgn(const double& x) {return x < -zero ? -1 : x > zero ? 1 : 0;} /* sgn */ inline double sqr(const double& x) {return x * x;} /* sqr */ inline int cmp(const void* __a, const void* __b) { const HP &a = *(HP*)__a, &b = *(HP*)__b; int tmp = sgn(a.ang - b.ang); if (tmp) return tmp; return sgn((b.B - a.A) * (b.A - a.A)); } /* cmp */ inline bool eql(const HP& a, const HP& b) {return !sgn(a.ang - b.ang);} /* eql */ inline vec cross(const HP& a, const HP& b) { vec AB = a.B - a.A, CD = b.B - b.A, AC = b.A - a.A, AD = b.B - a.A; return a.A + AB * ((AC * AD) / (AB * CD)); } /* cross */ inline bool notin(const vec& P, const HP& a) {return (P - a.B) * (P - a.A) > -zero;} /* notin */ inline bool Half_Plane_Inter(const HP* fir, const HP* la) { static deque <HP> q; q.clear(); for (q.push_back(*fir++), q.push_back(*fir++); fir != la; q.push_back(*fir++)) { while (q.size() > 1 && notin(cross(*(q.end() - 2), q.back()) , *fir)) q.pop_back (); while (q.size() > 1 && notin(cross(q.front(), *(q.begin() + 1)), *fir)) q.pop_front(); } /* for */ for (;;) { bool flag = 0; while (q.size() > 2 && notin(cross(*(q.end() - 2), q.back()) , q.front())) q.pop_back (), flag = 1; while (q.size() > 2 && notin(cross(q.front(), *(q.begin() + 1)), q.back ())) q.pop_front(), flag = 1; if (!flag) break; } /* for */ return q.size() > 2; } /* Half_Plane_Inter */ inline bool check(double d) { for (int i = 0; i < n; ++i) { double x1 = hp[i].A.x, x2 = hp[i].B.x, y1 = hp[i].A.y, y2 = hp[i].B.y, len = hp[i].len; hp1[i].A.x = x1 + (y1 - y2) * d / len; hp1[i].B.x = x2 + (y1 - y2) * d / len; hp1[i].A.y = y1 + (x2 - x1) * d / len; hp1[i].B.y = y2 + (x2 - x1) * d / len; } /* for */ return Half_Plane_Inter(hp1, hp1 + n); } /* check */ int main() { freopen("sea.in" , "r", stdin ); freopen("sea.out", "w", stdout); while (~scanf("%d", &n) && n) { for (int i = 0; i < n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y); p[n] = p[0]; for (int i = 0; i < n; ++i) hp[i] = HP(p[i], p[i + 1]); std::qsort(hp, n, sizeof hp[0], cmp); n = std::unique(hp, hp + n, eql) - hp; double L = 0, R = 1e4; while (L - R < -zero) { double Mid = (L + R) / 2; if (check(Mid)) L = Mid; else R = Mid; } /* while */ printf("%.10lf\n", R); } /* while */ return 0; } /* main */ /* 相当于是求多边形内切圆半径。 只需要二分枚举,然后将所有的边向内移动半径的距离,求对应的半平面是否有相交的区域。 */zoj2820 How I Mathematician Wonder What You Are!
/************************************************************\ * @prob: zoj2820 How I Mathematician Wonder What You Are! * * @auth: Wang Junji * @stat: Accepted. * * @date: June. 26th. 2012 * @memo: 半平面交、多边形内核 * \************************************************************/ #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> #include <deque> #include <cmath> using std::deque; const int maxN = 50; const double zero = 1e-8; struct vec { double x, y; vec() {} /* vec */ vec(const vec& b): x(b.x), y(b.y) {} /* vec */ vec(double x, double y): x(x), y(y) {} /* vec */ vec& operator=(const vec& b) {x = b.x, y = b.y; return *this;} /* operator= */ vec operator-(const vec& b) const {return vec(x - b.x, y - b.y);} /* operator- */ vec operator+(const vec& b) const {return vec(x + b.x, y + b.y);} /* operator+ */ vec operator*(const double& d) const {return vec(x * d, y * d);} /* operator+ */ double operator*(const vec& b) const {return x * b.y - y * b.x;} /* operator* */ } p[maxN]; struct HP { vec A, B; HP() {} /* HP */ HP(const HP& b): A(b.A), B(b.B) {} /* HP */ HP(const vec& A, const vec& B): A(A), B(B) {} /* HP */ HP& operator=(const HP& b) {A = b.A, B = b.B; return *this;} /* HP */ operator vec() const {return B - A;} /* operator vec */ double operator*(const HP& b) const {return (B - A) * (b.B - b.A);} /* operator* */ double angle() const {return atan2(B.y - A.y, B.x - A.x);} /* angle */ } ele[maxN]; int n; vec cross(const HP& a, const HP& b) { vec AB = vec(a), CD = vec(b), AC = b.A - a.A, AD = b.B - a.A; return a.A + AB * ((AC * AD) / (AB * CD)); } /* cross */ inline int sgn(const double& x) {return x < -zero ? -1 : x > zero ? 1 : 0;} /* sgn */ inline int cmp(const void* __a, const void* __b) { const HP &a = *(HP*)__a, &b = *(HP*)__b; int tmp = sgn(a.angle() - b.angle()); if (tmp) return tmp; return sgn((b.B - a.A) * (b.A - a.A)); } /* cmp */ inline bool eql(const HP& a, const HP& b) {return !sgn(a.angle() - b.angle());} /* eql */ inline bool notin(const vec& P, const HP& a) {return (P - a.B) * (P - a.A) > -zero;} /* notin */ bool Core(HP const* fir, HP const* la) { static deque <HP> q; q.clear(); for (q.push_back(*fir++), q.push_back(*fir++); fir != la; q.push_back(*fir++)) { while (q.size() > 1 && notin(cross(*(q.end() - 2), q.back()), *fir)) q.pop_back(); while (q.size() > 1 && notin(cross(q.front(), *(q.begin() + 1)), *fir)) q.pop_front(); } /* for */ for (;;) { bool flag = 0; while (q.size() > 2 && notin(cross(*(q.end() - 2), q.back()), q.front())) q.pop_back(), flag = 1; while (q.size() > 2 && notin(cross(q.front(), *(q.begin() + 1)), q.back())) q.pop_front(), flag = 1; if (!flag) break; } /* for */ return q.size() > 2; } /* Core */ int main() { freopen("Core.in" , "r", stdin ); freopen("Core.out", "w", stdout); while (~scanf("%d", &n) && n) { for (int i = 0; i < n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y); p[n] = p[0]; for (int i = 0; i < n; ++i) ele[i] = HP(p[i], p[i + 1]); qsort(ele, n, sizeof ele[0], cmp); n = std::unique(ele, ele + n, eql) - ele; printf("%d\n", Core(ele, ele + n)); } /* while */ return 0; } /* main */ /* 半平面交模板题。 参考 http://evalls.yo2.cn/articles/%E5%8D%8A%E5%B9%B3%E9%9D%A2%E4%BA%A4onlogn%E7%9A%84%E7%AE%97%E6%B3%95.html 1) 将所有半平面按极角排序,对于极角相同的,选择性的保留一个。 2) 使用一个双端队列(deque),加入最开始2个半平面。 3) 每次考虑一个新的半平面: a. while deque顶端的两个半平面的交点在当前半平面外:删除deque顶端的半平面 b. while deque底部的两个半平面的交点在当前半平面外:删除deque底部的半平面 c. 将新半平面加入deque顶端 4) 删除两端多余的半平面。 具体方法是: a. while deque顶端的两个半平面的交点在底部半平面外:删除deque顶端的半平面 b. while deque底部的两个半平面的交点在顶端半平面外:删除deque底部的半平面 重复a, b直到不能删除为止。 5) 计算出deque顶端和底部的交点即可。 */