HDU 6617 Enveloping Convex(凸包+半平面交+二分)
首先对于这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(凸包+半平面交+二分)的更多相关文章
- HDU 3761 炸碉堡【半平面交(nlogn)】+【二分】
<题目链接> < 转载于 > 题目大意: 给出一个凸多边形,顶点为一些防御塔,保护范围是凸多形内部,不包括边界,在多边形内部选择一点,使得对方至少需要摧毁的塔防数量最多 ...
- POJ 3525 Most Distant Point from the Sea [半平面交 二分]
Most Distant Point from the Sea Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 5153 ...
- 简单几何(半平面交+二分) LA 3890 Most Distant Point from the Sea
题目传送门 题意:凸多边形的小岛在海里,问岛上的点到海最远的距离. 分析:训练指南P279,二分答案,然后整个多边形往内部收缩,如果半平面交非空,那么这些点构成半平面,存在满足的点. /******* ...
- POJ 3525 Most Distant Point from the Sea (半平面交+二分)
Most Distant Point from the Sea Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3476 ...
- [模板] 计算几何2: 自适应Simpson/凸包/半平面交/旋转卡壳/闵可夫斯基和
一些基本的定义在这里: [模板] 计算几何1(基础): 点/向量/线/圆/多边形/其他运算 自适应Simpson Simpson's Rule: \[ \int ^b_a f(x)dx\approx ...
- POJ 3525 半平面交+二分
二分所能形成圆的最大距离,然后将每一条边都向内推进这个距离,最后所有边组合在一起判断时候存在内部点 #include <cstdio> #include <cstring> # ...
- UVA 3890 Most Distant Point from the Sea(二分法+半平面交)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11358 [思路] 二分法+半平面交 二分与海边的的距离,由法向量可 ...
- [2019HDU多校第四场][HDU 6617][D. Enveloping Convex]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6617 题目大意:给出一凸包\(P\),求最小的与\(P\)相似且对应边平行的多边形,使得题目给出的\( ...
- UVa 1475 (二分+半平面交) Jungle Outpost
题意: 有n个瞭望塔构成一个凸n边形,敌人会炸毁一些瞭望台,剩下的瞭望台构成新的凸包.在凸多边形内部选择一个点作为总部,使得敌人需要炸毁的瞭望塔最多才能使总部暴露出来.输出敌人需要炸毁的数目. 分析: ...
随机推荐
- 模块打包 webpack
1.模块打包工具 2.工作方式: 1)将存在依赖关系的模块按照特定规则合并为单个JS文件,一次全部加载进页面中 2)在页面初始时加载一个入口模块,其他模块异步的进行加载 3.优势: 1)支持AMD,C ...
- CF547E Mike and Friends
子串看起来就很SuffixStructures 于是上SAM 本来想着直接LCT 后来发现没法串定位(暴力匹配复杂度不对) 然后就离线吧,先建出来然后链加子树和,树剖就odk. 其实更直接的套路是线段 ...
- Python---进阶---文件操作---搜索文件和保存搜索结果
### 编写一个程序,用户输入文件名以及开始搜索的路径,搜索该文件是否存在,如果遇到文件夹,则进入该文件夹继续搜索 - input 去接受用户输入的文件名和开始搜索的路径 - os.path.isdi ...
- 【leetcode】1138. Alphabet Board Path
题目如下: On an alphabet board, we start at position (0, 0), corresponding to character board[0][0]. Her ...
- HTML页面滑动到最底部触发事件
其实基本原理做一个判断,如果 页面总高度 = 视口高度 + 浏览器窗口上边界内容高度 ,那么就是把页面滑动到了最低部,然后执行一个事件. //要触发的事件(自己定义事件的内容) functio ...
- 最大 k 乘积问题 ( 经典区间DP )
题意 : 设 NUM 是一个 n 位十进制整数.如果将 NUM 划分为 k 段,则可得到 k 个整数.这 k 个整数的乘积称为 NUM 的一个 k 乘积.试设计一个算法,对于给定的 NUM 和 k,求 ...
- SPOJ 2798 QTREE3 - Query on a tree again!
原oj题面 Time limit 2000 ms Memory limit 1572864 kB Code length Limit 50000 B OS Linux Language limit A ...
- python 获取某个文件下的所有文件
import os files = os.listdir(load_Graph_file_path) cnt = 0 for file in files: print(file) if (os.pat ...
- PS4 Submission
第一部分是param.sfo文件的设置: 另外,sce_sys目录下的icon0.png文件和pic1.png文件也可以手动修改成自己需要的样式,前者是在游戏中的logo,图片要求是512x512,p ...
- layer.open()中属性content在IE 8中提示“网页无法显示”
将图中的${ctx}值为 将${ctx}更改为BASEURI 如图: 若是在IE8上中弹出框中还是显示网页无法显示.可以改为 content:‘http://127.0.0.1:8081/projec ...