poj 3384 Feng Shui (Half Plane Intersection)
构造半平面交,然后求凸包上最远点对。
这题的题意是给出一个凸多边形区域,要求在其中放置两个半径为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-;
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) < || sgn(a.x - b.x) == && a.y < b.y;}
bool operator == (Point a, Point b) { return sgn(a.x - b.x) == || sgn(a.y - b.y) == ;} 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 = ; i < sz; i++) {
ret += crossDet(pt[i], pt[i - ]);
}
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) > ;}
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[n];
DLine *q = new DLine[n];
q[fi = la = ] = L[];
for (int i = ; i < n; i++) {
while (fi < la && !onLeft(L[i], p[la - ])) la--;
while (fi < la && !onLeft(L[i], p[fi])) fi++;
q[++la] = L[i];
if (fabs(crossDet(q[la].v, q[la - ].v)) < EPS) {
la--;
if (onLeft(q[la], L[i].p)) q[la] = L[i];
}
if (fi < la) p[la - ] = dLineIntersect(q[la - ], q[la]);
}
while (fi < la && !onLeft(q[fi], p[la - ])) 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 = ;
Point pt[N];
DLine dl[N]; int main() {
// freopen("in", "r", stdin);
int n;
double r;
while (cin >> n >> r) {
for (int i = ; i < n; i++) {
cin >> pt[i].x >> pt[i].y;
if (i) dl[i - ] = DLine(pt[i], pt[i - ] - pt[i]).move(r + EPS);
}
dl[n - ] = DLine(pt[], pt[n - ] - pt[]).move(r + EPS);
Poly tmp = halfPlane(dl, n);
if (tmp.size() <= ) {
for (int i = ; i < n; i++) {
if (i) dl[i - ] = DLine(pt[i], pt[i - ] - pt[i]).move(r - EPS);
}
dl[n - ] = DLine(pt[], pt[n - ] - pt[]).move(r - EPS);
tmp = halfPlane(dl, n);
}
double dis = 0.0;
int id[] = { , };
n = tmp.size();
for (int i = ; i < n; i++) {
for (int j = ; j < n; j++) {
if (dis < vecLen(tmp[i] - tmp[j])) {
dis = vecLen(tmp[i] - tmp[j]);
id[] = i;
id[] = j;
}
}
}
// cout << vecLen(tmp[id[0]] - tmp[id[1]]) << endl;
cout.precision();
cout << tmp[id[]].x << ' ' << tmp[id[]].y << ' ' << tmp[id[]].x << ' ' << tmp[id[]].y << endl;
}
return ;
}
吸取教训,继续努力!
——written by Lyon
poj 3384 Feng Shui (Half Plane Intersection)的更多相关文章
- POJ 3384 Feng Shui 半平面交
题目大意:一个人很信"Feng Shui",他要在房间里放两个圆形的地毯. 这两个地毯之间可以重叠,可是不能折叠,也不能伸到房间的外面.求这两个地毯可以覆盖的最大范围.并输出这两个 ...
- POJ 3384 Feng Shui (半平面交)
Feng Shui Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 3743 Accepted: 1150 Speci ...
- POJ 3384 Feng Shui(计算几何の半平面交+最远点对)
Description Feng shui is the ancient Chinese practice of placement and arrangement of space to achie ...
- POJ 3384 Feng Shui
http://poj.org/problem?id=3384 题意:给一个凸包,求往里面放两个圆(可重叠)的最大面积时的两个圆心坐标. 思路:先把凸包边往内推R,做半平面交,然后做旋转卡壳,此时得到最 ...
- POJ 3384 Feng Shui --直线切平面
题意:房间是一个凸多边形,要在里面铺设两条半径为r的圆形地毯,可以重叠,现在要求分别铺设到哪,使地毯所占的地面面积最大. 解法:要使圆形地毯所占面积最大,圆形地毯一定是与边相切的,这样才能使尽量不重叠 ...
- POJ 3384 Feng Shui(半平面交向内推进求最远点对)
题目链接 题意 : 两个圆能够覆盖的最大多边形面积的时候两个圆圆心的坐标是多少,两个圆必须在多边形内. 思路 : 向内推进r,然后求多边形最远的两个点就是能覆盖的最大面积. #include < ...
- POJ 3384 Feng Shui 凸包直径 + 半平面交
G++一直没有过了 换成 C++果断A掉了...It's time to bet RP. 题意:给一个多边形,然后放进去两个圆,让两个圆的覆盖面积尽量最大,输出两个圆心的坐标. 思路:将多边形的边向里 ...
- poj 3335 Rotating Scoreboard (Half Plane Intersection)
3335 -- Rotating Scoreboard 给出一个多边形,要求判断它的内核是否存在. 还是半平面交的题,在这道题中,公告板允许其所在位置与直线共线也算是可见,于是我们就可以将每一条直线微 ...
- poj 1279 Art Gallery (Half Plane Intersection)
1279 -- Art Gallery 还是半平面交的问题,要求求出多边形中可以观察到多边形所有边的位置区域的面积.其实就是把每一条边看作有向直线然后套用半平面交.这题在输入的时候应该用多边形的有向面 ...
随机推荐
- Python 五个知识点搞定作用域
Python 五个知识点搞定作用域 1.块级作用域 想想此时运行下面的程序会有输出吗?执行会成功吗? #块级作用域 if 1 == 1: name = "lzl" print(na ...
- Android——<uses-sdk>
语法(SYNTAX): <uses-sdk android:minSdkVersion="integer" android:targetSdkVersion="in ...
- JavaScript字符串、数组、对象方法总结
字符串方法 示例字符串: const str = "hello,kitty,hello,vue "; 一.基本方法 charAt(n) 返回指定索引的字符 charCodeAt(n ...
- Linux 配置yum源(互联网)
Linux 配置yum源(互联网) 环境:操作系统Redhat 7.5 1.卸载现有的yum源 rpm -qa|grep yum|xargs rpm -e --nodeps #移除与原yum有 ...
- 修改mysql数据库密码的3中方法
方法1: 用SET PASSWORD命令 mysql -u root mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpass ...
- CMD格式数据表输出语句
mysql --default-character-set=latin1 -uroot -p
- PSPP:顶替SPSS常用功能的优秀软件, Linux 下的经济学用软件
几个替代SPSS的软体Salstat http://salstat.sourceforge.net/PSPP http://www.gnu.org/software/pspp/pspp.htmlR h ...
- op应用:官方,wifidog,portal,uci,luci,脚本,框架,usb
http://wiki.openwrt.org/doc/starthttp://downloads.openwrt.org/docs/buildroot-documentation.htmlhttp: ...
- larbin终于编译完成
1.目前sourceforge不能下载,只能找mirror进行下载了: 2.一些头文件始终找不到,定位了一下,应该是makefile中设置有问题,把CXXFLAGS中的-I-去掉,即可编译成功:
- Timer和DispatcherTimer简单使用
1. 设定计时器相关属性,使用委托方法处理事件触发 DispatcherTimer dispatcherTimer= new DispatcherTimer(); dispatcherTimer.Ti ...