这是一道半平面交的裸题,第一次写半平面交,就说一说我对半平面交的理解吧。

所谓半平面交,就是求一大堆二元一次不等式的交集,而每个二元一次不等式的解集都可以看成是在一条直线的上方或下方,联系直线的标准方程就可以得出。于是乎这些不等式就可以转化为一些半平面,求的就是半平面交。

而半平面交不可能交出凹多边形(因为凹多边形的定义是有一条边所在的直线能把该多边形分成若干块。。。YY一下就知道这是不可能的),这是一个十分优美的性质,正类似于凸包(写法也是有些相似的),但半平面交可能交出无界,于是可以加四条类似于一个框的直线将这个区域框起来,就可以避免无界情况的出现,当然也可能交出无解,一个点或一条直线(俩点),判一判就好了。

有一个十分暴力的n^2做法,就是每次加一条直线,暴力去判与当前直线的交点,然后判断哪些部分不可行,哪些部分可行。。。(十分暴力,而且十分难写。。。。)

也有两个(可能是三个。。。不过后两个思想类似)nlogn的做法,一种是分治,将当前的半平面数分治,递归去找,然后利用扫描线扫过去。。。。不过常数大而且不易编写

还有另一个nlogn的做法,就是维护一个单调栈,用一个上凸壳和一个下凸壳处理,方法是如果直线stack[top]与当前直线a[i]交点在当前的半平面外就top--,然后把得到的一个上凸壳和一个下凸壳合并即可

但合并还是有些麻烦,就可以用一个双向队列维护一个凸壳,每次加入一条直线就判队头和队尾然后加在队尾,但具体实现过程中可能会出现问题,因为令极角递增(都是看成逆时针旋转,这样比较方便),所以当前直线的极角一定比队列中所有直线的极角都要大,因此对答案是一定有贡献的(也就是一定会是边界,在不被后面的直线判掉的情况下),在维护两个单调栈时并不用考虑(貌似合并时也要考虑),但deque是一个环,因此到最后的直线的斜率虽然大,但并不一定会对半平面产生贡献(毕竟每一次都是queue[++tail]=a[i]),因此就还需要两遍while判队头队尾什么的。这样十分方便而且核心代码巨短。。。。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 2000
#define eps 1e-0 int n,m,tot,cnt; struct point{
double x,y;
}p[maxn],pt[maxn]; struct line{
point from,to;
double slope;
}l[maxn],q[maxn]; point operator -(point a,point b){return(point){a.x-b.x,a.y-b.y};}
point operator +(point a,point b){return(point){a.x+b.x,a.y+b.y};}
double operator *(point a,point b){return a.x*b.y-a.y*b.x;}
bool operator <(line a,line b){
return (a.slope==b.slope)?((a.to-a.from)*(b.to-a.from)<):a.slope<b.slope;
}
bool operator ==(line a,line b){
return a.slope==b.slope;
} point getpoint(line a,line b){
double t1=(b.to-a.from)*(a.to-a.from),t2=(a.to-a.from)*(b.from-a.from);
double t=t1/(t1+t2);
return (point){(b.from.x-b.to.x)*t+b.to.x,(b.from.y-b.to.y)*t+b.to.y};
} bool check(line a,line b,line c){
point d=getpoint(a,b);
return (c.to-c.from)*(d-c.from)<;
} void solve(){
int head=,tail=;
q[]=l[],q[]=l[];
for (int i=;i<=n;i++){
while (head<tail && check(q[tail-],q[tail],l[i])) tail--;
while (head<tail && check(q[head+],q[head],l[i])) head++;
q[++tail]=l[i];
}
while (head<tail && check(q[tail-],q[tail],q[head])) tail--;
while (head<tail && check(q[head+],q[head],q[tail])) head++;
q[tail+]=q[head],cnt=;
for (int i=head;i<=tail;i++) pt[++cnt]=getpoint(q[i],q[i+]);
} int main(){
scanf("%d",&n);
for (int i=;i<=n;i++){
scanf("%d",&m);
for (int j=;j<=m;j++) scanf("%lf %lf",&p[j].x,&p[j].y);
p[m+]=p[];
for (int j=;j<=m;j++) l[++tot].from=p[j],l[tot].to=p[j+];
}
for (int i=;i<=tot;i++) l[i].slope=atan2(l[i].to.y-l[i].from.y,l[i].to.x-l[i].from.x);
sort(l+,l+tot+);
n=;
n=unique(l+,l+tot+)-l;
n--;
solve();
double ans=;
if (cnt<=){
printf("0.000");
return ;
}
pt[++cnt]=pt[];
for (int i=;i<=cnt;i++) ans+=pt[i]*pt[i+];
printf("%.3lf",ans/);
return ;
}

bzoj2618[Cqoi2006]凸多边形 半平面交的更多相关文章

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

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

  2. 【bzoj2618】[Cqoi2006]凸多边形 半平面交

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

  3. P4196 [CQOI2006]凸多边形 半平面交

    \(\color{#0066ff}{题目描述}\) 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. \(\color{#0066f ...

  4. luogu4196 [CQOI2006]凸多边形 半平面交

    据说pkusc出了好几年半平面交了,我也来水一发 ref #include <algorithm> #include <iostream> #include <cstdi ...

  5. POJ3525 半平面交

    题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似 ...

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

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

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

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

  8. bzoj 3190 赛车 半平面交

    直接写的裸的半平面交,已经有点背不过模板了... 这题卡精度,要用long double ,esp设1e-20... #include<iostream> #include<cstd ...

  9. BZOJ 4445 [Scoi2015]小凸想跑步:半平面交

    传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...

随机推荐

  1. Xcode部分插件无法使用识别的问题

    1. 首先查看 Xcode 的 UUID,在终端执行 defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilit ...

  2. 用Jsoup实现html中img标签地址替换

    做app的时候经常要用webview解析Html,如果是自己写的服务器那么富文本编辑框有可能选择像KindEditor这样的编辑器,在kindEditor添加图片虽然可以实现绝对路径插入,如果说: & ...

  3. windows蓝屏代码大全及常见蓝屏解决方案

    对于以下的代码查询建议使用ctrl+F查询,而且很多蓝屏与黑屏的问题多是最近操作引起的,例如更新驱动,安装新的硬件.软件--把相关的配置调到最近的正常状况大多可以解决,确实不行时方可考虑重装系统,解决 ...

  4. 仿写thinkphp的I方法

    自己定义一个方法仿写thinkphp的I 方法 <?php function I($key="",$default='',$function="") { ...

  5. 【Unity Shaders】使用CgInclude让你的Shader模块化——创建CgInclude文件存储光照模型

    本系列主要參考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同一时候会加上一点个人理解或拓展. 这里是本书全部的插图. 这里是本书所需的代码 ...

  6. MySQL 慢查询

    MySQL优化 [TOC] 1,定位慢查询 -------------------------- 增.删.改10%,查询90% 数据库引擎 MyISAM:不支持事务,用于只读程序提高性能 InnoDB ...

  7. [HTTP2] HTTP1 probs and HTTP2 saves

    1. HOL (HEADS of LINE BLOCKING) Too many requests in the header tag. Broswer can allow 6 reuqest to ...

  8. Linux 的启动流程-阮一峰

    http://www.ruanyifeng.com/blog/2013/08/linux_boot_process.html

  9. Building and setting up QT environment for BeagleBone

    There are too few information available on how to easily setup QT environment for building Beaglebon ...

  10. yum在线升级

    RPM优点 由於 RPM 是透过预先编译并打包成为 RPM 文件格式后,再加以安装的一种方式,并且还能够进行数据库的记载. 所以 RPM 有以下的优点: RPM 内含已经编译过的程序与配置档等数据,可 ...