题意:求某凸多边形内部离边界最远的点到边界的距离

首先介绍半平面、半平面交的概念:

半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围。如图所示:

半平面交:多个半平面的交集。有点类似二元函数的线性规划。如图

求半平面交:用的kuangbin模板= =

sol:二分答案

  二分距离值,按这个值把边界向内缩,再求新的半平面交。如图:

绿色的是原图形,蓝色是按距离值向里面缩进去之后得到的新图形。对这个新图做半平面交即可。

若半平面交存在,说明与边界的距离是该值的点存在(半平面交里面的点都是)

那么如何把图形向里面缩呢?其实在纸上画画就容易多了:

因为半平面是一条有向直线,所以只要有直线上的任意一点和方向就可以了,这个点在不在对应的那条边上都无所谓。

如图,棕色是一开始的边,黑色是它对应的半平面。

设当前二分答案值是mid,对这条边做一个长度为mid的法向量(图中绿色)

棕色边起点+法向量即得到新半平面上的一个点(图中蓝色)

新半平面的方向和原来一样,直接平移过来就行了。

在做法向量的时候采用向量的概念能简化问题。这里在kuangbin模板的基础上加上了向量类Vector:

 struct Vector:public point
{
Vector(){}
Vector(double a,double b)
{
x=a; y=b;
}
Vector(point _a,point _b) //a->b
{
double dx=_b.x-_a.x;
double dy=_b.y-_a.y;
x=dx; y=dy;
}
Vector(line v)
{
double dx=v.b.x-v.a.x;
double dy=v.b.y-v.a.y;
x=dx; y=dy;
}
double length()
{
return (sqrt(x*x+y*y));
}
Vector Normal() //返回this的单位长度的法向量
{
double L=sqrt(x*x+y*y);
Vector Vans=Vector(-y/L,x/L);
return Vans;
}
};

重载了三种构造函数:给出向量的坐标值(x,y)、给出向量首尾两点、用一条线段作为向量

----------------------------------------------

AC Code:

 #include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
#define mp make_pair
#define pb push_back
using namespace std;
const double eps=1e-;
const double pi=acos(-1.0);
const double inf=1e20;
const int maxp=;
int dblcmp(double d)
{
if (fabs(d)<eps)return ;
return d>eps?:-;
}
inline double sqr(double x){return x*x;}
struct point
{
double x,y;
point(){}
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==(point a)const
{
return dblcmp(a.x-x)==&&dblcmp(a.y-y)==;
}
bool operator<(point a)const
{
return dblcmp(a.x-x)==?dblcmp(y-a.y)<:x<a.x;
}
double len()
{
return hypot(x,y);
}
double len2()
{
return x*x+y*y;
}
double distance(point p)
{
return hypot(x-p.x,y-p.y);
}
point add(point p)
{
return point(x+p.x,y+p.y);
}
point sub(point p)
{
return point(x-p.x,y-p.y);
}
point mul(double b)
{
return point(x*b,y*b);
}
point div(double b)
{
return point(x/b,y/b);
}
double dot(point p)
{
return x*p.x+y*p.y;
}
double det(point p)
{
return x*p.y-y*p.x;
}
double rad(point a,point b)
{
point p=*this;
return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
}
point trunc(double r)
{
double l=len();
if (!dblcmp(l))return *this;
r/=l;
return point(x*r,y*r);
}
point rotleft()
{
return point(-y,x);
}
point rotright()
{
return point(y,-x);
}
point rotate(point p,double angle)//绕点p逆时针旋转angle角度
{
point v=this->sub(p);
double c=cos(angle),s=sin(angle);
return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
}
};
struct line
{
point a,b;
line(){}
line(point _a,point _b)
{
a=_a;
b=_b;
}
bool operator==(line v)
{
return (a==v.a)&&(b==v.b);
}
//倾斜角angle
line(point p,double angle)
{
a=p;
if (dblcmp(angle-pi/)==)
{
b=a.add(point(,));
}
else
{
b=a.add(point(,tan(angle)));
}
}
//ax+by+c=0
line(double _a,double _b,double _c)
{
if (dblcmp(_a)==)
{
a=point(,-_c/_b);
b=point(,-_c/_b);
}
else if (dblcmp(_b)==)
{
a=point(-_c/_a,);
b=point(-_c/_a,);
}
else
{
a=point(,-_c/_b);
b=point(,(-_c-_a)/_b);
}
}
void input()
{
a.input();
b.input();
}
void adjust()
{
if (b<a)swap(a,b);
}
double length()
{
return a.distance(b);
}
double angle()//直线倾斜角 0<=angle<180
{
double k=atan2(b.y-a.y,b.x-a.x);
if (dblcmp(k)<)k+=pi;
if (dblcmp(k-pi)==)k-=pi;
return k;
}
//点和线段关系
//1 在逆时针
//2 在顺时针
//3 平行
int relation(point p)
{
int c=dblcmp(p.sub(a).det(b.sub(a)));
if (c<)return ;
if (c>)return ;
return ;
}
bool pointonseg(point p)
{
return dblcmp(p.sub(a).det(b.sub(a)))==&&dblcmp(p.sub(a).dot(p.sub(b)))<=;
}
bool parallel(line v)
{
return dblcmp(b.sub(a).det(v.b.sub(v.a)))==;
}
//2 规范相交
//1 非规范相交
//0 不相交
int segcrossseg(line v)
{
int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));
int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));
if ((d1^d2)==-&&(d3^d4)==-)return ;
return (d1==&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=||
d2==&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=||
d3==&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=||
d4==&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=);
}
int linecrossseg(line v)//*this seg v line
{
int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
if ((d1^d2)==-)return ;
return (d1==||d2==);
}
//0 平行
//1 重合
//2 相交
int linecrossline(line v)
{
if ((*this).parallel(v))
{
return v.relation(a)==;
}
return ;
}
point crosspoint(line v)
{
double a1=v.b.sub(v.a).det(a.sub(v.a));
double a2=v.b.sub(v.a).det(b.sub(v.a));
return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
}
double dispointtoline(point p)
{
return fabs(p.sub(a).det(b.sub(a)))/length();
}
double dispointtoseg(point p)
{
if (dblcmp(p.sub(b).dot(a.sub(b)))<||dblcmp(p.sub(a).dot(b.sub(a)))<)
{
return min(p.distance(a),p.distance(b));
}
return dispointtoline(p);
}
point lineprog(point p)
{
return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));
}
point symmetrypoint(point p)
{
point q=lineprog(p);
return point(*q.x-p.x,*q.y-p.y);
}
}; struct Vector:public point
{
Vector(){}
Vector(double a,double b)
{
x=a; y=b;
}
Vector(point _a,point _b) //a->b
{
double dx=_b.x-_a.x;
double dy=_b.y-_a.y;
x=dx; y=dy;
}
Vector(line v)
{
double dx=v.b.x-v.a.x;
double dy=v.b.y-v.a.y;
x=dx; y=dy;
}
double length()
{
return (sqrt(x*x+y*y));
}
Vector Normal()
{
double L=sqrt(x*x+y*y);
Vector Vans=Vector(-y/L,x/L);
return Vans;
}
}; struct halfplane:public line //半平面
{
double angle;
halfplane(){}
//表示向量 a->b逆时针(左侧)的半平面
halfplane(point _a,point _b)
{
a=_a;
b=_b;
}
halfplane(line v)
{
a=v.a;
b=v.b;
}
void calcangle()
{
angle=atan2(b.y-a.y,b.x-a.x);
}
bool operator<(const halfplane &b)const
{
return angle<b.angle;
}
};
struct halfplanes //半平面交
{
int n;
halfplane hp[maxp];
point p[maxp];
int que[maxp];
int st,ed;
void push(halfplane tmp)
{
hp[n++]=tmp;
}
void unique()
{
int m=,i;
for (i=;i<n;i++)
{
if (dblcmp(hp[i].angle-hp[i-].angle))hp[m++]=hp[i];
else if (dblcmp(hp[m-].b.sub(hp[m-].a).det(hp[i].a.sub(hp[m-].a))>))hp[m-]=hp[i];
}
n=m;
}
bool halfplaneinsert()
{
int i;
for (i=;i<n;i++)hp[i].calcangle();
sort(hp,hp+n);
unique();
que[st=]=;
que[ed=]=;
p[]=hp[].crosspoint(hp[]);
for (i=;i<n;i++)
{
while (st<ed&&dblcmp((hp[i].b.sub(hp[i].a).det(p[ed].sub(hp[i].a))))<)ed--;
while (st<ed&&dblcmp((hp[i].b.sub(hp[i].a).det(p[st+].sub(hp[i].a))))<)st++;
que[++ed]=i;
if (hp[i].parallel(hp[que[ed-]]))return false;
p[ed]=hp[i].crosspoint(hp[que[ed-]]);
}
while (st<ed&&dblcmp(hp[que[st]].b.sub(hp[que[st]].a).det(p[ed].sub(hp[que[st]].a)))<)ed--;
while (st<ed&&dblcmp(hp[que[ed]].b.sub(hp[que[ed]].a).det(p[st+].sub(hp[que[ed]].a)))<)st++;
if (st+>=ed)return false;
return true;
}
/*
void getconvex(polygon &con)
{
p[st]=hp[que[st]].crosspoint(hp[que[ed]]);
con.n=ed-st+1;
int j=st,i=0;
for (;j<=ed;i++,j++)
{
con.p[i]=p[j];
}
}*/
}; point p[];
Vector V[],Vt[];
halfplanes TH;
int n; int main()
{
//freopen("in.txt","r",stdin); while (cin>>n)
{
if (n==) break;
for (int i=;i<n;i++) //n points:[0..n-1]
p[i].input(); for (int i=;i<n;i++) //v[i]:p[i]->p[i+1]
{
V[i]=Vector(p[i],p[(i+)%n]);
//printf("vector: %.6lf %.6lf\n",V[i].x,V[i].y);
Vt[i]=V[i].Normal();
} double l=,r=;
while (r-l>eps)
{
double mid=(l+r)/;
//double mid=l+(r-l)/2;
TH.n=;
//halfplanes TH; for (int i=;i<n;i++)
{
point t1=p[i].add(Vt[i].mul(mid));
point t2=t1.add(V[i]); line tmp=line(t1,t2);
TH.push(halfplane(tmp));
} //printf("%.6lf %d",mid,TH.n); if (TH.halfplaneinsert())
{
//cout<<"OK"<<endl;
l=mid; //l=mid+0.00001;
}
else
{
//cout<<"NO"<<endl;
r=mid; //r=mid-0.00001;
}
}
printf("%.6lf\n",l);
}
return ;
}

推荐iPad上一个免费又好用的绘图板:Sketches

POJ3525 半平面交的更多相关文章

  1. 【kuangbin专题】计算几何_半平面交

    1.poj3335 Rotating Scoreboard 传送:http://poj.org/problem?id=3335 题意:就是有个球场,球场的形状是个凸多边形,然后观众是坐在多边形的边上的 ...

  2. 【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交

    4515: [Sdoi2016]游戏 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 129[Submit][Status][ ...

  3. poj3335 半平面交

    题意:给出一多边形.判断多边形是否存在一点,使得多边形边界上的所有点都能看见该点. sol:在纸上随手画画就可以找出规律:按逆时针顺序连接所有点.然后找出这些line的半平面交. 题中给出的点已经按顺 ...

  4. POJ 3130 How I Mathematician Wonder What You Are! /POJ 3335 Rotating Scoreboard 初涉半平面交

    题意:逆时针给出N个点,求这个多边形是否有核. 思路:半平面交求多边形是否有核.模板题. 定义: 多边形核:多边形的核可以只是一个点,一条直线,但大多数情况下是一个区域(如果是一个区域则必为 ).核内 ...

  5. bzoj2618[Cqoi2006]凸多边形 半平面交

    这是一道半平面交的裸题,第一次写半平面交,就说一说我对半平面交的理解吧. 所谓半平面交,就是求一大堆二元一次不等式的交集,而每个二元一次不等式的解集都可以看成是在一条直线的上方或下方,联系直线的标准方 ...

  6. POJ 3384 Feng Shui 半平面交

    题目大意:一个人很信"Feng Shui",他要在房间里放两个圆形的地毯. 这两个地毯之间可以重叠,可是不能折叠,也不能伸到房间的外面.求这两个地毯可以覆盖的最大范围.并输出这两个 ...

  7. BZOJ2618[Cqoi2006]凸多边形——半平面交

    题目描述 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. 输入 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形.第 ...

  8. 洛谷P3222 [HNOI2012]射箭(计算几何,半平面交,双端队列)

    洛谷题目传送门 设抛物线方程为\(y=ax^2+bx(a<0,b>0)\),我们想要求出一组\(a,b\)使得它尽可能满足更多的要求.这个显然可以二分答案. 如何check当前的\(mid ...

  9. bzoj 4445 小凸想跑步 - 半平面交

    题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...

随机推荐

  1. “Word自动更改后的内容保存到通用文档模板上。是否加载该模板?“的解决办法

    在win7系统下,Word2010出现了不能正常关闭.打开一个已有word文档,点击右上角关闭按钮后,先提示"word已停止工作,windows正在检查该问题的解决方案",随后提示 ...

  2. 数据挖掘系列(9)——BP神经网络算法与实践

    神经网络曾经很火,有过一段低迷期,现在因为深度学习的原因继续火起来了.神经网络有很多种:前向传输网络.反向传输网络.递归神经网络.卷积神经网络等.本文介绍基本的反向传输神经网络(Backpropaga ...

  3. PHP 基础笔记

    数据类型 字符串 整数 浮点数 布尔值 数组 对象 NULL 未定义的变量,数据类型为 NULL. PHP 中数组和对象是不同的类型,而 js 中数组即为对象.(ps: es6 已经内置了 class ...

  4. css3实践之图片轮播(Transform,Transition和Animation)

    楼主喜欢追求视觉上的享受,虽常以牺牲性能无法兼容为代价却也乐此不疲.本文就通过一个个的demo演示来简单了解下css3下的Transform,Transition和Animation. 本文需要实现效 ...

  5. C#开发Windows服务

    Microsoft Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序. 服务可以在计算机启动时自动启动,可以暂停和重新启动而且 ...

  6. [poj2484]A Funny Game(对称博弈)

    题目:http://poj.org/problem?id=2484 题意:n个石子围成一个圈,两个人轮流取,每次可以取一个石子或者相邻的两个石子,问先手胜还是后手胜 分析: 典型的对称博弈 如果n&g ...

  7. Linux运维初级、中级、高级

    学习Linux,好的教程.使学习事半功倍! 老男孩Linux.shell.RHCE运维初中高级 下载地址: http://pan.baidu.com/s/1sB3VC 马哥教育Linux初级.中级.高 ...

  8. 安装rpm包时遇到Header V3 DSA signature: NOKEY时解决办法

    安装rpm包,特别是没有GPGkey校验,原因是rpm版本过低导致的. 代码如下: warning: rpmts_HdrFromFdno: Header V3 DSA signature: NOKEY ...

  9. Beta版本冲刺Day6

    会议讨论: 628:配置Mysql的时候遇到了问题,在修改数据库用户密码时无法修改,并且服务器好像连接不上去了,其他组员则继续他们的任务.601:将一些原来的界面进行了修改,修改成了更加美观的外形. ...

  10. Servlet从本地文件中读取图片,并显示在页面中

    import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpSer ...