您的位置:首页 > 产品设计 > UI/UE

poj 3384 Feng Shui (Half Plane Intersection)

2013-06-21 05:56 288 查看
3384 -- Feng Shui

  构造半平面交,然后求凸包上最远点对。

  这题的题意是给出一个凸多边形区域,要求在其中放置两个半径为r的圆(不能超出凸多边形区域),要求求出两个圆心,使得多边形中没有被覆盖的面积最小。反之就是求圆覆盖的区域最大。首先我们可以求出圆心放置的位置的区域,这个要利用半平面交,将原多边形区域向内收缩r的距离。要求两个圆覆盖的区域最大,也就是它们相交的面积最小,也就是两个圆心的距离要尽可能的大。这样就说明了,这题的做法是要求出凸包上面的最远点对。

  做这题的时候犯了两个错误,一个是没有设置对精度,直接用了cout的默认输出,另一个则是没有想到收缩以后,剩余的多边形的顶点数会少于n。

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
} ;
template<class T> T sqr(T x) { return x * x;}

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

const double EPS = 1e-8;
const double PI = acos(-1.0);
inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
bool operator < (Point a, Point b) { return sgn(a.x - b.x) < 0 || sgn(a.x - b.x) == 0 && a.y < b.y;}
bool operator == (Point a, Point b) { return sgn(a.x - b.x) == 0 || sgn(a.y - b.y) == 0;}

inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
inline double dotDet(Point o, Point a, Point b) { return dotDet(a - o, b - o);}
inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
inline double vecLen(Vec x) { return sqrt(dotDet(x, x));}
inline double toRad(double deg) { return deg/ 180.0 * PI;}
inline double angle(Vec v) { return atan2(v.y, v.x);}
Vec normal(Vec x) {
double len = vecLen(x);
return Vec(-x.y, x.x) / len;
}

struct Poly {
vector<Point> pt;
Poly() { pt.clear();}
~Poly() {}
Poly(vector<Point> &pt) : pt(pt) {}
Point operator [] (int x) const { return pt[x];}
int size() { return pt.size();}
double area() {
double ret = 0.0;
int sz = pt.size();
for (int i = 1; i < sz; i++) {
ret += crossDet(pt[i], pt[i - 1]);
}
return fabs(ret / 2.0);
}
} ;

struct DLine {
Point p;
Vec v;
double ang;
DLine() {}
DLine(Point p, Vec v) : p(p), v(v) { ang = atan2(v.y, v.x);}
bool operator < (const DLine &L) const { return ang < L.ang;}
DLine move(double x) {
Vec nor = normal(v);
nor = nor * x;
return DLine(p + nor, v);
}
} ;

inline bool onLeft(DLine L, Point p) { return crossDet(L.v, p - L.p) > 0;}
Point dLineIntersect(DLine a, DLine b) {
Vec u = a.p - b.p;
double t = crossDet(b.v, u) / crossDet(a.v, b.v);
return a.p + a.v * t;
}

Poly halfPlane(DLine *L, int n) {
Poly ret = Poly();
sort(L, L + n);
int fi, la;
Point *p = new Point
;
DLine *q = new DLine
;
q[fi = la = 0] = L[0];
for (int i = 1; i < n; i++) {
while (fi < la && !onLeft(L[i], p[la - 1])) la--;
while (fi < la && !onLeft(L[i], p[fi])) fi++;
q[++la] = L[i];
if (fabs(crossDet(q[la].v, q[la - 1].v)) < EPS) {
la--;
if (onLeft(q[la], L[i].p)) q[la] = L[i];
}
if (fi < la) p[la - 1] = dLineIntersect(q[la - 1], q[la]);
}
while (fi < la && !onLeft(q[fi], p[la - 1])) la--;
if (la < fi) return ret;
p[la] = dLineIntersect(q[la], q[fi]);
for (int i = fi; i <= la; i++) ret.pt.push_back(p[i]);
return ret;
}

const int N = 111;
Point pt
;
DLine dl
;

int main() {
//    freopen("in", "r", stdin);
int n;
double r;
while (cin >> n >> r) {
for (int i = 0; i < n; i++) {
cin >> pt[i].x >> pt[i].y;
if (i) dl[i - 1] = DLine(pt[i], pt[i - 1] - pt[i]).move(r + EPS);
}
dl[n - 1] = DLine(pt[0], pt[n - 1] - pt[0]).move(r + EPS);
Poly tmp = halfPlane(dl, n);
if (tmp.size() <= 1) {
for (int i = 0; i < n; i++) {
if (i) dl[i - 1] = DLine(pt[i], pt[i - 1] - pt[i]).move(r - EPS);
}
dl[n - 1] = DLine(pt[0], pt[n - 1] - pt[0]).move(r - EPS);
tmp = halfPlane(dl, n);
}
double dis = 0.0;
int id[2] = { 0, 0};
n = tmp.size();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (dis < vecLen(tmp[i] - tmp[j])) {
dis = vecLen(tmp[i] - tmp[j]);
id[0] = i;
id[1] = j;
}
}
}
//        cout << vecLen(tmp[id[0]] - tmp[id[1]]) << endl;
cout.precision(9);
cout << tmp[id[0]].x << ' ' << tmp[id[0]].y << ' ' << tmp[id[1]].x << ' ' << tmp[id[1]].y << endl;
}
return 0;
}


View Code
  吸取教训,继续努力!

——written by Lyon
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: