首先对于这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. 量子计算机不会“秒杀”经典计算机
  2. 2015国产手机圈成绩单
  3. 华为升级鸿蒙体验,华为鸿蒙 HarmonyOS 2.0 发布,教你如何升级体验
  4. Shell脚本中循环语句for,while,until用法
  5. BAT面试进阶:最全Memcached面试30题含答案
  6. 13 PP配置-生产主数据-BOM相关-定义修正参数
  7. [转]javascript 程序1
  8. Hibernate (load PK get and list PK iterator )
  9. windows 下 git bash 打开特定的文件目录与相关操作
  10. 卡巴斯基KEY文件的类型选择
  11. 如何对PDF文件的文字图片编辑修改
  12. 去除最新版WinRAR的弹窗广告
  13. linux程序设计学习心得,几点学习Linux编程的建议
  14. Win11家庭版远程桌面不支持怎么办
  15. JAVA之旅(三十五)——完结篇,终于把JAVA写完了,真感概呐!
  16. 个人总结-oracle查询锁表、解锁语句
  17. 【你好,windows】Windows 10 20H2 19042.630专业工作站纯净版2020.12.1
  18. 中国幼儿教育市场运营模式与未来发展方向分析报告2022版
  19. 天津地铁行业建设现状与运营状况分析报告2022版
  20. 07-ET框架的数据库连接

热门文章

  1. 带答案APP测试面试题分享,助攻你的面试!面试官都惊呆了..
  2. matlab中imresize函数
  3. new FileReader()
  4. HDU-2544 最短路【最短路】
  5. PC epub阅读器推荐
  6. bandgap的理解(内部带隙电压基准)
  7. 项目管理之人力资源管理
  8. 高中数学基础-2.1.1(1)根式的运算
  9. python程序员培训_Python程序员学习路线图
  10. 「Java」冒泡排序