首先对于这m个点维护出一个凸包M,那么问题就变成了判断凸包P进行放大缩小能不能包含凸包M。(凸包P可以进行中心对称变换再进行放大缩小,见题意)

如何判断合适的相似比呢,我们可以用二分去放大缩小凸包P的坐标,得到最小的相似比。

接下来就是如何判断是否包含。我们需要对凸包P上的每一条向量,在凸包M上找到这么一个点,使得这个点左侧的所有凸包M上的点都在向量的左侧,那么我们可以直接同时逆时针枚举,用一个变量维护凸包M上的点,因为是同逆时针,凸包M上的点至少有一个只会被遍历一次,那么复杂度可以证明为On,这样就可以维护出来凸包P上的向量所对应的在凸包M上的点。因为包含关系,满足所有的向量的对应点都应该在向量的左侧,那么我们将这个向量相对于这个点的坐标求出来,然后维护一个半平面交是否有解即可,判断这个半平面交维护出来的是否是一个合法的凸包,当然由于我们是逆时针枚举的向量,需要先对凸包P进行逆时针转动,所以我们没必要将这些相对于坐标的向量排序,直接维护半平面交,但是最后我们需要判断维护出来的凸包是否严格按照逆时针旋转,因为位置是相对的,可能出现一个向下的向量的左侧是一个向上的向量,这样的关系是矛盾的。

注意细节,由于我的模板用的是求直线交点,精度比较差,eps开的比较小。

  1 //        ——By DD_BOND
  2
  3 //#include<bits/stdc++.h>
  4 //#include<unordered_map>
  5 //#include<unordered_set>
  6 #include<functional>
  7 #include<algorithm>
  8 #include<iostream>
  9 //#include<ext/rope>
 10 #include<iomanip>
 11 #include<climits>
 12 #include<cstring>
 13 #include<cstdlib>
 14 #include<cstddef>
 15 #include<cstdio>
 16 #include<memory>
 17 #include<vector>
 18 #include<cctype>
 19 #include<string>
 20 #include<cmath>
 21 #include<queue>
 22 #include<deque>
 23 #include<ctime>
 24 #include<stack>
 25 #include<map>
 26 #include<set>
 27
 28 #define fi first
 29 #define se second
 30 #define MP make_pair
 31 #define pb push_back
 32
 33 #pragma GCC optimize(3)
 34 #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
 35
 36 typedef long long ll;
 37
 38 using namespace std;
 39
 40 const int MAXN=1e5+10;
 41 const double eps=1e-18;
 42 const double pi=acos(-1.0);
 43 const ll INF=0x3f3f3f3f3f3f3f3f;
 44
 45 inline int dcmp(double x){
 46     if(fabs(x)<eps)    return 0;
 47     return (x>0? 1: -1);
 48 }
 49
 50 inline double sqr(double x){ return x*x; }
 51
 52 struct Point{
 53     double x,y;
 54     Point(){ x=0,y=0; }
 55     Point(double _x,double _y):x(_x),y(_y){}
 56     void input(){ scanf("%lf%lf",&x,&y); }
 57     void output(){ printf("%.2f %.2f\n",x,y); }
 58     bool operator <(const Point &b)const{
 59         return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x);
 60     }
 61     double operator ^(const Point &b)const{        //叉积
 62         return x*b.y-y*b.x;
 63     }
 64     double operator *(const Point &b)const{        //点积
 65         return x*b.x+y*b.y;
 66     }
 67     bool operator ==(const Point &b)const{
 68         return dcmp(x-b.x)==0&&dcmp(y-b.y)==0;
 69     }
 70     Point operator +(const Point &b)const{
 71         return Point(x+b.x,y+b.y);
 72     }
 73     Point operator -(const Point &b)const{
 74         return Point(x-b.x,y-b.y);
 75     }
 76     Point operator *(double a){
 77         return Point(x*a,y*a);
 78     }
 79     Point operator /(double a){
 80         return Point(x/a,y/a);
 81     }
 82     double len2(){    //长度平方
 83         return sqr(x)+sqr(y);
 84     }
 85     double len(){   //长度
 86         return sqrt(len2());
 87     }
 88 };
 89
 90 inline double cross(Point a,Point b){    //叉积
 91     return a.x*b.y-a.y*b.x;
 92 }
 93
 94 inline double dot(Point a,Point b){    //点积
 95     return a.x*b.x+a.y*b.y;
 96 }
 97
 98 struct Line{
 99     Point s,e;
100     Line(){}
101     Line(Point _s,Point _e):s(_s),e(_e){}
102     Point operator &(const Line &b)const{     //求两直线交点
103         Point res=s;
104         double t=((s-b.s)^(b.s-b.e))/(((s-e)^(b.s-b.e))+eps);
105         res.x+=(e.x-s.x)*t;
106         res.y+=(e.y-s.y)*t;
107         return res;
108     }
109 };
110
111 int relation(Point p,Line l){    //点和向量关系   1:左侧   2:右侧   3:在线上
112     int c=dcmp(cross(p-l.s,l.e-l.s));
113     if(c<0)    return 1;
114     else if(c>0)    return 2;
115     else    return 3;
116 }
117
118 bool counter_wise(Point *p,int n){            //多边形点集调整为逆时针顺序
119     for(int i=1;i<n-1;i++)
120         if(dcmp(cross(p[i]-p[i-1],p[i+1]-p[i-1]))>0)    return 0;
121         else if(dcmp(cross(p[i]-p[i-1],p[i+1]-p[i-1]))<0){
122             reverse(p,p+n);
123             return 1;
124         }
125     return 1;
126 }
127
128 Point tmp[MAXN];
129 int convex_hull(Point *p,int n,Point *ch){    //求凸包
130     int m=0;
131     sort(p,p+n);
132     for(int i=0;i<n;i++){
133         while(m>1&&dcmp(cross(tmp[m-1]-tmp[m-2],p[i]-tmp[m-1]))<=0)    m--;
134         tmp[m++]=p[i];
135     }
136     int k=m;
137     for(int i=n-2;i>=0;i--){
138         while(m>k&&dcmp(cross(tmp[m-1]-tmp[m-2],p[i]-tmp[m-1]))<=0)    m--;
139         tmp[m++]=p[i];
140     }
141     if(n>1)    m--;
142     for(int i=0;i<m;i++)    ch[i]=tmp[i];
143     return m;
144 }
145
146 Line que[MAXN];
147 int half_plane_intersection(Line *L,int n){    //以逆时针方向 半平面交求多边形的核  ch表示凸包的顶点  返回顶点数 -1则表示不存在
148     int head=0,tail=1;
149     que[0]=L[0],que[1]=L[1];
150     for(int i=2;i<n;i++){
151         while(tail>head&&relation(que[tail]&que[tail-1],L[i])==2)   tail--;
152         while(tail>head&&relation(que[head]&que[head+1],L[i])==2)   head++;
153         que[++tail]=L[i];
154     }
155     while(tail>head&&relation(que[tail]&que[tail-1],que[head])==2)  tail--;
156     while(tail>head&&relation(que[head]&que[head+1],que[tail])==2)  head++;
157     for(int i=head;i<=tail;i++){
158         int j=(i==tail? head: i+1);
159         if(dcmp(cross(que[i].e-que[i].s,que[j].e-que[j].s))<=0)
160             return 0;
161     }
162     return 1;
163 }
164
165 Line line[MAXN];
166 Point p[MAXN],q[MAXN],ops[MAXN];
167
168 int main(void){
169     int T;  scanf("%d",&T);
170     while(T--){
171         int n;  scanf("%d",&n);
172         for(int i=0;i<n;i++)    p[i].input();
173         int m;  scanf("%d",&m);
174         for(int i=0;i<m;i++)    q[i].input();
175         counter_wise(p,n);  m=convex_hull(q,m,q);
176         double ans=INF;
177         for(int t=1;t<=2;t++){
178             for(int i=0;i<n;i++)    p[i]=Point(-p[i].x,-p[i].y);
179             for(int i=0,j=0;i<n;i++){
180                 while(dcmp(cross(p[(i+1)%n]-p[i],q[(j-1+m)%m]-q[j]))<0||dcmp(cross(p[(i+1)%n]-p[i],q[(j+1)%m]-q[j]))<0)   j=(j+1)%m;
181                 ops[i]=q[j];
182             }
183             double l=0,r=1e10;
184             for(int i=0;i<70;i++){
185                 double mid=(l+r)/2;
186                 for(int j=0;j<n;j++)    line[j]=Line(p[j]*mid-ops[j],p[(j+1)%n]*mid-ops[j]);
187                 if(half_plane_intersection(line,n)) r=mid;
188                 else    l=mid;
189             }
190             ans=min(ans,l);
191         }
192         printf("%.10lf\n",ans);
193     }
194     return 0;
195 }

转载于:https://www.cnblogs.com/dd-bond/p/11308219.html

HDU 6617 Enveloping Convex(凸包+半平面交+二分)相关推荐

  1. UVA1396 Most Distant Point from the Sea(AM - ICPC - Tokyo - 2007)(计算几何,半平面交 + 二分答案)

    整理的算法模板合集: ACM模板 题目传送门 见<训练指南>P279 很明显就是一个二分答案,它问的是最远的点,直接枚举因为这里都是double类型的数所以有无限个点,我们可以直接二分. ...

  2. [模板] 计算几何2: 自适应Simpson/凸包/半平面交/旋转卡壳/闵可夫斯基和

    一些基本的定义在这里: [模板] 计算几何1(基础): 点/向量/线/圆/多边形/其他运算 自适应Simpson Simpson's Rule: \[ \int ^b_a f(x)dx\approx ...

  3. [2019HDU多校第四场][HDU 6617][D. Enveloping Convex]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6617 题目大意:给出一凸包\(P\),求最小的与\(P\)相似且对应边平行的多边形,使得题目给出的\( ...

  4. Polygons HDU - 1632 (半平面交)

    Polygons HDU - 1632 题意:求两个多边形的"异或"面积. 半平面交~ 1 #include <bits/stdc++.h> 2 using namespace std; ...

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

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

  6. LA 3890 (半平面交) Most Distant Point from the Sea

    题意: 给出一个凸n边形,求多边形内部一点使得该点到边的最小距离最大. 分析: 最小值最大可以用二分. 多边形每条边的左边是一个半平面,将这n个半平面向左移动距离x,则将这个凸多边形缩小了.如果这n个 ...

  7. [凸多边形最大内切圆][半平面交]Most Distant Point from the Sea POJ3525

    The main land of Japan called Honshu is an island surrounded by the sea. In such an island, it is na ...

  8. 模板:半平面交(计算几何)

    所谓半平面交,就是和"半平先生"当面交谈.顾名思义,这是一个源于日本的算法. (逃) 前言 感觉应用很灵活的一个算法,一切有两个变量的线性规划问题都可以转化为半平面交. 有时可能要 ...

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

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

最新文章

  1. IntelliJ IDEA sass环境配置及常见报错处理
  2. Linux系统中,read文件过程分析
  3. 启明云端分享| SSD201 / SSD202D 在IP广播的应用
  4. 【CodeForces - 271B 】Prime Matrix (素数,预处理打表,思维)
  5. 彭山计算机培训,彭山2021年初中生学计算机
  6. Debian下使用OpenLDAP
  7. windows应用x64和x86运行效率_现在你可以在 Windows 中运行 Linux 应用了 | Linux 中国...
  8. 【ArcGIS|空间分析】求年度NDVI最大值图像和NDVI最大值出现日期图像
  9. 协作,才能更好的中断线程
  10. 删除本地.svn文件
  11. 车牌定位html5,车牌识别(一)——车牌定位(附详细代码及注释)
  12. 【论文笔记】FlowNet:有监督的光流估计(optical flow estimation)网络
  13. kron matlab_Matlab运用kron()函数计算Kronecker乘法
  14. 进程管理——PV操作
  15. uniapp 请求接口封装
  16. win10 microsoft edge 浏览器收藏夹位置
  17. 使用Jmeter批量测试视频链接可用性
  18. lol桌面图标在计算机哪找,玩英雄联盟重新创建桌面图标的方法
  19. 软件推广样例:爱情银行APP日流超50w原因分析
  20. 福建师范大学计算机专业研究生,福建师范大学研究生专业排名

热门文章

  1. C语言winmain函数的参数,c++:谁调用了main/WinMain函数!
  2. 【微信小程序】轮播图——swpier组件
  3. Mac 上 VMware 安装 win7 虚拟机如何添加磁盘
  4. 【数学】函数极限计算
  5. KITTI 自动驾驶 数据集 镜像 百度网盘 百度云 下载
  6. 应聘简历/邮件怎样写
  7. nmap常用命令有哪些
  8. 日志数据如何同步到MaxCompute
  9. Vue ajax跨域请求*
  10. 私有vlan(PVLAN)实验配置步骤