3384 -- Feng Shui

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

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

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

代码如下:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <cmath>
  7
  8 using namespace std;
  9
 10 struct Point {
 11     double x, y;
 12     Point() {}
 13     Point(double x, double y) : x(x), y(y) {}
 14 } ;
 15 template<class T> T sqr(T x) { return x * x;}
 16
 17 typedef Point Vec;
 18 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
 19 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
 20 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
 21 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
 22
 23 const double EPS = 1e-8;
 24 const double PI = acos(-1.0);
 25 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
 26 bool operator < (Point a, Point b) { return sgn(a.x - b.x) < 0 || sgn(a.x - b.x) == 0 && a.y < b.y;}
 27 bool operator == (Point a, Point b) { return sgn(a.x - b.x) == 0 || sgn(a.y - b.y) == 0;}
 28
 29 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
 30 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
 31 inline double dotDet(Point o, Point a, Point b) { return dotDet(a - o, b - o);}
 32 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
 33 inline double vecLen(Vec x) { return sqrt(dotDet(x, x));}
 34 inline double toRad(double deg) { return deg/ 180.0 * PI;}
 35 inline double angle(Vec v) { return atan2(v.y, v.x);}
 36 Vec normal(Vec x) {
 37     double len = vecLen(x);
 38     return Vec(-x.y, x.x) / len;
 39 }
 40
 41 struct Poly {
 42     vector<Point> pt;
 43     Poly() { pt.clear();}
 44     ~Poly() {}
 45     Poly(vector<Point> &pt) : pt(pt) {}
 46     Point operator [] (int x) const { return pt[x];}
 47     int size() { return pt.size();}
 48     double area() {
 49         double ret = 0.0;
 50         int sz = pt.size();
 51         for (int i = 1; i < sz; i++) {
 52             ret += crossDet(pt[i], pt[i - 1]);
 53         }
 54         return fabs(ret / 2.0);
 55     }
 56 } ;
 57
 58 struct DLine {
 59     Point p;
 60     Vec v;
 61     double ang;
 62     DLine() {}
 63     DLine(Point p, Vec v) : p(p), v(v) { ang = atan2(v.y, v.x);}
 64     bool operator < (const DLine &L) const { return ang < L.ang;}
 65     DLine move(double x) {
 66         Vec nor = normal(v);
 67         nor = nor * x;
 68         return DLine(p + nor, v);
 69     }
 70 } ;
 71
 72 inline bool onLeft(DLine L, Point p) { return crossDet(L.v, p - L.p) > 0;}
 73 Point dLineIntersect(DLine a, DLine b) {
 74     Vec u = a.p - b.p;
 75     double t = crossDet(b.v, u) / crossDet(a.v, b.v);
 76     return a.p + a.v * t;
 77 }
 78
 79 Poly halfPlane(DLine *L, int n) {
 80     Poly ret = Poly();
 81     sort(L, L + n);
 82     int fi, la;
 83     Point *p = new Point[n];
 84     DLine *q = new DLine[n];
 85     q[fi = la = 0] = L[0];
 86     for (int i = 1; i < n; i++) {
 87         while (fi < la && !onLeft(L[i], p[la - 1])) la--;
 88         while (fi < la && !onLeft(L[i], p[fi])) fi++;
 89         q[++la] = L[i];
 90         if (fabs(crossDet(q[la].v, q[la - 1].v)) < EPS) {
 91             la--;
 92             if (onLeft(q[la], L[i].p)) q[la] = L[i];
 93         }
 94         if (fi < la) p[la - 1] = dLineIntersect(q[la - 1], q[la]);
 95     }
 96     while (fi < la && !onLeft(q[fi], p[la - 1])) la--;
 97     if (la < fi) return ret;
 98     p[la] = dLineIntersect(q[la], q[fi]);
 99     for (int i = fi; i <= la; i++) ret.pt.push_back(p[i]);
100     return ret;
101 }
102
103 const int N = 111;
104 Point pt[N];
105 DLine dl[N];
106
107 int main() {
108 //    freopen("in", "r", stdin);
109     int n;
110     double r;
111     while (cin >> n >> r) {
112         for (int i = 0; i < n; i++) {
113             cin >> pt[i].x >> pt[i].y;
114             if (i) dl[i - 1] = DLine(pt[i], pt[i - 1] - pt[i]).move(r + EPS);
115         }
116         dl[n - 1] = DLine(pt[0], pt[n - 1] - pt[0]).move(r + EPS);
117         Poly tmp = halfPlane(dl, n);
118         if (tmp.size() <= 1) {
119             for (int i = 0; i < n; i++) {
120                 if (i) dl[i - 1] = DLine(pt[i], pt[i - 1] - pt[i]).move(r - EPS);
121             }
122             dl[n - 1] = DLine(pt[0], pt[n - 1] - pt[0]).move(r - EPS);
123             tmp = halfPlane(dl, n);
124         }
125         double dis = 0.0;
126         int id[2] = { 0, 0};
127         n = tmp.size();
128         for (int i = 0; i < n; i++) {
129             for (int j = 0; j < n; j++) {
130                 if (dis < vecLen(tmp[i] - tmp[j])) {
131                     dis = vecLen(tmp[i] - tmp[j]);
132                     id[0] = i;
133                     id[1] = j;
134                 }
135             }
136         }
137 //        cout << vecLen(tmp[id[0]] - tmp[id[1]]) << endl;
138         cout.precision(9);
139         cout << tmp[id[0]].x << ' ' << tmp[id[0]].y << ' ' << tmp[id[1]].x << ' ' << tmp[id[1]].y << endl;
140     }
141     return 0;
142 }

View Code

  吸取教训,继续努力!

——written by Lyon

转载于:https://www.cnblogs.com/LyonLys/p/poj_3384_Lyon.html

poj 3384 Feng Shui (Half Plane Intersection)相关推荐

  1. POJ - 3384 Feng Shui(半平面交)

    链接 Feng Shui 题意 将两个半径为 rrr 的圆放入一个多边形中,两个圆占据最大面积时圆心坐标是多少: 思路 在多边形中放圆,最大圆的圆心一定在多边形内核中: 将多边形的每条边都内推 rrr ...

  2. poj 3384 Feng Shui 半平面交

    http://poj.org/problem?id=3384 给定一个多边形,在多边形内放有两个相同的圆,使两个圆尽可能多的覆盖多边形.输出最终两个圆心的位置. 最优的放置方法必定是圆内切于两条边,那 ...

  3. POJ 3384 Feng Shui(半平面交)

    题意 : 给你一个凸多边形,让你在其中找两个圆,使得圆的覆盖面积最大. 这个题目和 poj 3525 有点类似,那个题目是一个圆,想到两者的联系,可以发现两个圆覆盖面积最大就是重叠面积最小,怎样使得重 ...

  4. POJ 3384 Feng Shui

    坑爹的题,,就是先向内推进r,然后半平面交得出圆心范围. 然后旋转卡壳求最远点对 这道题首先样例给的就不对,不知道什么情况 然后一直WA,后来看了discuss,试了下这组数据: 4 1 0 0 0 ...

  5. Feng Shui POJ - 3384 [半平面交]

    Feng Shui POJ - 3384 题意:n个顶点的凸包,放入2个半径为r的圆,可以重叠,要求面积最大,输出2个圆的圆心坐标(保留4位小数) 思路:找出圆心的可行域(内推r,求半平面交),再求核 ...

  6. CodeForces - Feng Shui(半平面交)

    题目链接:http://codeforces.com/gym/101650/attachments Time Limit: 2000MS Memory Limit: 65536K Descriptio ...

  7. Feng Shui POJ - 3384

    题目链接:https://cn.vjudge.net/problem/POJ-3384 #include<cstdio> #include<cstring> #include& ...

  8. [POJ3384]Feng Shui(半平面交+凸包)

    题目: 我是超链接 题意: 在一个凸多边形中放两个半径固定的圆,要求输出使覆盖面积最大的(可重叠)两个圆圆心 题解: Emmm...套路缩小凸多边形,形成的凸包是圆心可以在的位置,然后暴力找最远点! ...

  9. Using the five elements of fashion colors to create the best feng shui in auspicious Home

    Romania, just a legend Licheng Peng Galaxy SOHO opening-day sales 46 Pan Shiyi Students start the On ...

最新文章

  1. 一线程序员年薪90万,不敢结婚不敢要孩子,被父母怼:堂弟月薪4千二胎都有了,家里最挫的就是我!...
  2. 『Lucas定理以及拓展Lucas』
  3. ssl提高组周六模拟赛【2018.9.15】
  4. 使用ZeroTier搭建大局域网利用VNC远程桌面
  5. 19.Linux-USB总线驱动分析
  6. 用Bi-GRU语义解析,实现中文人物关系分析 | 附完整代码
  7. Win7使用之查端口,杀进程
  8. Revit二次开发之ISelectionFilter 接口的用法
  9. c++实现tailf命令
  10. uni-app微信小程序——商城(8)——订单详情
  11. 怎么把分开的pdf放在一起_PDF多页合并为一页的方法是什么 怎么将PDF文件拆分成单页...
  12. syn重发_TCP/IP中SYN,FIN的缩写意思
  13. Mysql从入门到入魔——6. 表联结、组合查询
  14. Android手机接入usb屏幕失灵,手机屏幕失灵了怎么办?安卓手机屏幕失灵解决方法...
  15. upupoo启动不了 mysql_显示桌面快捷方式
  16. npm install报错 npm ERR 的四种解决办法
  17. matlab设置图片背景透明_Matlab ---- 有透明度的png图像的显示与图层叠加方法
  18. .Net开发 开发工具使用vs C盘占用空间不断增大
  19. 攻防世界 Reverse进阶区 BABYRE WP
  20. YDOOK AI : Pytorch :使用 tensor.zeros() tensor.zeros_like() 生成定义 全零数组 全0数组

热门文章

  1. 上班能赚到第一桶金吗?
  2. 现在生意不是能不能干的问题
  3. 二十六岁,裸辞之后,我步入了“三无”行列
  4. sort()与cmp()
  5. Zookeeper节点详解
  6. ssis for循环容器_SSIS包中的序列容器
  7. sql azure 语法_Azure Data Studio中SQL代码段
  8. 有关SQL Server代理的常见问题和示例
  9. 如何对SQL Server实例执行性能测试
  10. CTO 深度解读 SMTX OS 3.5 产品特性