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

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

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

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

求半平面交:用的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. Linux 网络编程详解六(多进程服务器僵尸进程解决方案)

    小结:在点对点p2p程序中,服务器端子程序退出,子进程会主动发送信号,关闭父进程,但是这种模式导致服务器只能支持一个客户端连接,本章节中使用新的框架,子进程退出,不主动发送信号关闭父进程,而是父进程安 ...

  2. JAVA CDI 学习(1) - @Inject基本用法

    CDI(Contexts and Dependency Injection 上下文依赖注入),是JAVA官方提供的依赖注入实现,可用于Dynamic Web Module中,先给3篇老外的文章,写得很 ...

  3. ReactNative真机运行指南

    ReactNative真机运行指南 注意在iOS设备上运行React Native应用需要一个Apple Developer account并且把你的设备注册为测试设备.本向导只包含React Nat ...

  4. QT 智能提示设置

    qt5.0的智能提示设置 qt默认的是Ctrl+空格 但这个是切换输入法,用着也不习惯 修改的地方是 工具->选项->环境 键盘选项把CompleteThis修改成自己习惯的快捷键

  5. js的offsetWidth,offsetHeight,offsetLeft,offsetTop

    js的offsetWidth,offsetHeight,offsetLeft,offsetTop

  6. 日志记录类库log4net的使用总结

    log4net是一个开源的日志记录类库,经过配置后可以自动抓取程序中的错误.异常信息,并写入磁盘,也可以在异常发生时执行其他指定的操作,比如:通知某人右键.写入数据库等.这里写个ASP.NET MVC ...

  7. 东大OJ 2SAT 异或

    看了十年才懂懂了十年才会会了十年才会写写了十年才写完写完了十年才能改对 #include<stdio.h> #include<string.h> struct res{ int ...

  8. iOS -- 神战

    http://github.ibireme.com/github/list/ios/# https://github.com/Tim9Liu9/TimLiu-iOS http://www.ios122 ...

  9. 25 uname-用于显示系统信息

    uname可显示电脑以及操作系统的相关信息. 语法 uname [-amnrsv][--help][--version] 参数说明: -a或--all 显示全部的信息. -m或--machine 显示 ...

  10. void与void之间没有隐式转换(纯属恶搞,请勿在意)

    强大的vs弹出了这个提示:.有没有觉得强大的vs不应该出现该提示. 但就是出现了. 看客,您知道怎么让vs弹出这个提示吗^~^