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边形,敌人会炸毁一些瞭望台,剩下的瞭望台构成新的凸包.在凸多边形内部选择一个点作为总部,使得敌人需要炸毁的瞭望塔最多才能使总部暴露出来.输出敌人需要炸毁的数目. 分析: ...
随机推荐
- eclipse把函数内容折叠的方法
eclipse 将方法折叠要先启动折叠功能启用方法:Ctrl+ / (小键盘) 或者:右键点击行号左边的空白,弹出的选项中,选择“Folding”下的“Enable Folding”这样启动foldi ...
- 【SaltStack官方版】—— Events&Reactor系统—EVENT SYSTEM
Events&Reactor系统 EVENT SYSTEM The Salt Event System is used to fire off events enabling third pa ...
- 【leetcode】1103. Distribute Candies to People
题目如下: We distribute some number of candies, to a row of n = num_people people in the following way: ...
- handy源码阅读(六):tcp类
首先是tcpconn和tcpserver类: struct TcpConn : public std::enable_shared_from_this<TcpConn>, private ...
- python+selenium实现经京东登录+购物+支付
import json from time import sleep from selenium import webdriver import chardet from selenium.webdr ...
- 微信小程序-wxml-空格
必须要在<text>标签中 先在标签中写decode="{{true}}"然后 就代表空格了 占一个中文字符
- 前端面试题常考&必考之--清除浮动的方法
浮动 问题:子元素设置了float后,脱离父元素,导致父元素无法撑开?(也就是子元素的高度没有过渡到父元素) 例子: 检查元素的效果: (三种)常用的解决办法: 1>额外标签法,添加一个空的di ...
- webstorm 点击右上角运行run 启动vue项目
点击右上角框 -> 编辑结构 点击加号 新增一个npm项目 前提:node环境已经安装完成,npm包管理器 1.进行定位到项目的路径2.安装依赖包,npm install3.启动服务,npm r ...
- 批量下载文件JSP
最近项目有个需求,用户想对挂有附件的数据记录 实现一键下载全部附件(目前项目仅支持每次点击单条记录进行附件下载),下面记录我实现的解决方案.项目框架基于SSMservice业务实现层(impl):// ...
- [HTML]时钟
<div class="clock" id="clock"> <!-- 原点 --> <div class="origi ...