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

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

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

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

 //        ——By DD_BOND

 //#include<bits/stdc++.h>
//#include<unordered_map>
//#include<unordered_set>
#include<functional>
#include<algorithm>
#include<iostream>
//#include<ext/rope>
#include<iomanip>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<cstddef>
#include<cstdio>
#include<memory>
#include<vector>
#include<cctype>
#include<string>
#include<cmath>
#include<queue>
#include<deque>
#include<ctime>
#include<stack>
#include<map>
#include<set> #define fi first
#define se second
#define MP make_pair
#define pb push_back #pragma GCC optimize(3)
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") typedef long long ll; using namespace std; const int MAXN=1e5+;
const double eps=1e-;
const double pi=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3f; inline int dcmp(double x){
if(fabs(x)<eps) return ;
return (x>? : -);
} inline double sqr(double x){ return x*x; } struct Point{
double x,y;
Point(){ x=,y=; }
Point(double _x,double _y):x(_x),y(_y){}
void input(){ scanf("%lf%lf",&x,&y); }
void output(){ printf("%.2f %.2f\n",x,y); }
bool operator <(const Point &b)const{
return (dcmp(x-b.x)==? dcmp(y-b.y)< : x<b.x);
}
double operator ^(const Point &b)const{ //叉积
return x*b.y-y*b.x;
}
double operator *(const Point &b)const{ //点积
return x*b.x+y*b.y;
}
bool operator ==(const Point &b)const{
return dcmp(x-b.x)==&&dcmp(y-b.y)==;
}
Point operator +(const Point &b)const{
return Point(x+b.x,y+b.y);
}
Point operator -(const Point &b)const{
return Point(x-b.x,y-b.y);
}
Point operator *(double a){
return Point(x*a,y*a);
}
Point operator /(double a){
return Point(x/a,y/a);
}
double len2(){ //长度平方
return sqr(x)+sqr(y);
}
double len(){ //长度
return sqrt(len2());
}
}; inline double cross(Point a,Point b){ //叉积
return a.x*b.y-a.y*b.x;
} inline double dot(Point a,Point b){ //点积
return a.x*b.x+a.y*b.y;
} struct Line{
Point s,e;
Line(){}
Line(Point _s,Point _e):s(_s),e(_e){}
Point operator &(const Line &b)const{ //求两直线交点
Point res=s;
double t=((s-b.s)^(b.s-b.e))/(((s-e)^(b.s-b.e))+eps);
res.x+=(e.x-s.x)*t;
res.y+=(e.y-s.y)*t;
return res;
}
}; int relation(Point p,Line l){ //点和向量关系 1:左侧 2:右侧 3:在线上
int c=dcmp(cross(p-l.s,l.e-l.s));
if(c<) return ;
else if(c>) return ;
else return ;
} bool counter_wise(Point *p,int n){ //多边形点集调整为逆时针顺序
for(int i=;i<n-;i++)
if(dcmp(cross(p[i]-p[i-],p[i+]-p[i-]))>) return ;
else if(dcmp(cross(p[i]-p[i-],p[i+]-p[i-]))<){
reverse(p,p+n);
return ;
}
return ;
} Point tmp[MAXN];
int convex_hull(Point *p,int n,Point *ch){ //求凸包
int m=;
sort(p,p+n);
for(int i=;i<n;i++){
while(m>&&dcmp(cross(tmp[m-]-tmp[m-],p[i]-tmp[m-]))<=) m--;
tmp[m++]=p[i];
}
int k=m;
for(int i=n-;i>=;i--){
while(m>k&&dcmp(cross(tmp[m-]-tmp[m-],p[i]-tmp[m-]))<=) m--;
tmp[m++]=p[i];
}
if(n>) m--;
for(int i=;i<m;i++) ch[i]=tmp[i];
return m;
} Line que[MAXN];
int half_plane_intersection(Line *L,int n){ //以逆时针方向 半平面交求多边形的核 ch表示凸包的顶点 返回顶点数 -1则表示不存在
int head=,tail=;
que[]=L[],que[]=L[];
for(int i=;i<n;i++){
while(tail>head&&relation(que[tail]&que[tail-],L[i])==) tail--;
while(tail>head&&relation(que[head]&que[head+],L[i])==) head++;
que[++tail]=L[i];
}
while(tail>head&&relation(que[tail]&que[tail-],que[head])==) tail--;
while(tail>head&&relation(que[head]&que[head+],que[tail])==) head++;
for(int i=head;i<=tail;i++){
int j=(i==tail? head: i+);
if(dcmp(cross(que[i].e-que[i].s,que[j].e-que[j].s))<=)
return ;
}
return ;
} Line line[MAXN];
Point p[MAXN],q[MAXN],ops[MAXN]; int main(void){
int T; scanf("%d",&T);
while(T--){
int n; scanf("%d",&n);
for(int i=;i<n;i++) p[i].input();
int m; scanf("%d",&m);
for(int i=;i<m;i++) q[i].input();
counter_wise(p,n); m=convex_hull(q,m,q);
double ans=INF;
for(int t=;t<=;t++){
for(int i=;i<n;i++) p[i]=Point(-p[i].x,-p[i].y);
for(int i=,j=;i<n;i++){
while(dcmp(cross(p[(i+)%n]-p[i],q[(j-+m)%m]-q[j]))<||dcmp(cross(p[(i+)%n]-p[i],q[(j+)%m]-q[j]))<) j=(j+)%m;
ops[i]=q[j];
}
double l=,r=1e10;
for(int i=;i<;i++){
double mid=(l+r)/;
for(int j=;j<n;j++) line[j]=Line(p[j]*mid-ops[j],p[(j+)%n]*mid-ops[j]);
if(half_plane_intersection(line,n)) r=mid;
else l=mid;
}
ans=min(ans,l);
}
printf("%.10lf\n",ans);
}
return ;
}

HDU 6617 Enveloping Convex(凸包+半平面交+二分)的更多相关文章

  1. HDU 3761 炸碉堡【半平面交(nlogn)】+【二分】

    <题目链接> <   转载于   > 题目大意: 给出一个凸多边形,顶点为一些防御塔,保护范围是凸多形内部,不包括边界,在多边形内部选择一点,使得对方至少需要摧毁的塔防数量最多 ...

  2. POJ 3525 Most Distant Point from the Sea [半平面交 二分]

    Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5153   ...

  3. 简单几何(半平面交+二分) LA 3890 Most Distant Point from the Sea

    题目传送门 题意:凸多边形的小岛在海里,问岛上的点到海最远的距离. 分析:训练指南P279,二分答案,然后整个多边形往内部收缩,如果半平面交非空,那么这些点构成半平面,存在满足的点. /******* ...

  4. POJ 3525 Most Distant Point from the Sea (半平面交+二分)

    Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3476   ...

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

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

  6. POJ 3525 半平面交+二分

    二分所能形成圆的最大距离,然后将每一条边都向内推进这个距离,最后所有边组合在一起判断时候存在内部点 #include <cstdio> #include <cstring> # ...

  7. UVA 3890 Most Distant Point from the Sea(二分法+半平面交)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11358 [思路] 二分法+半平面交 二分与海边的的距离,由法向量可 ...

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

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

  9. UVa 1475 (二分+半平面交) Jungle Outpost

    题意: 有n个瞭望塔构成一个凸n边形,敌人会炸毁一些瞭望台,剩下的瞭望台构成新的凸包.在凸多边形内部选择一个点作为总部,使得敌人需要炸毁的瞭望塔最多才能使总部暴露出来.输出敌人需要炸毁的数目. 分析: ...

随机推荐

  1. 前端之HTML:HTML

    前端基础之html 一.初始html 1.web服务本质 import socket sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) soc ...

  2. 字符编码 python2与python3的区别

    目录 1. 字符编码 2. 文本编辑器存储信息的过程 3. 编码: 1. 编码的历史 2. gb2312和gbk的区别 3. 编码和解码 4. python解释器 解释代码的流程 1. 读取文本到解释 ...

  3. Python---tkinter---贪吃蛇(能用的)

    项目分析:构成:蛇 Snake食物 Food世界 World蛇和食物属于整个世界  class World:      self.snake      self.food上面代码不太友好我们用另外一个 ...

  4. [CF1051F] Shortest Statement

    问题描述 You are given a weighed undirected connected graph, consisting of n vertices and m edges. You s ...

  5. vue的.sync 修饰符

    很多时候,我们会对 prop (父子组件传递数据的属性) 进行“双向绑定” 在vue 1.x 中的 .sync 修饰符所提供的功能.当一个子组件改变了一个带 .sync 的prop的值时,这个变化也会 ...

  6. linux运维、架构之路-Kubernetes集群部署

    一.kubernetes介绍        Kubernetes简称K8s,它是一个全新的基于容器技术的分布式架构领先方案.Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部 ...

  7. 内联元素的盒子模型与文档流定位padding属性

            内联元素的盒子模型 1.内联元素不能设置width宽度和高度height span{width:200px ; height:200px}   与     span{width:100 ...

  8. React Native 之FlatList

    1.新建项目 2.因为要用到导航跳转, 所以添加依赖,,这里拷贝这个: "dependencies": { "@types/react": "^16. ...

  9. B/S大文件下载+断点续传

    1.先将 webuploader-0.1.5.zip 这个文件下载下来:https://github.com/fex-team/webuploader/releases  根据个人的需求放置自己需要的 ...

  10. POJ 3061 Subsequence ( 二分 || 尺取法 )

    题意 : 找出给定序列长度最小的子序列,子序列的和要求满足大于或者等于 S,如果存在则输出最小长度.否则输出 0(序列的元素都是大于 0 小于10000) 分析 : 有关子序列和的问题,都可以考虑采用 ...