bzoj2618[Cqoi2006]凸多边形 半平面交
这是一道半平面交的裸题,第一次写半平面交,就说一说我对半平面交的理解吧。
所谓半平面交,就是求一大堆二元一次不等式的交集,而每个二元一次不等式的解集都可以看成是在一条直线的上方或下方,联系直线的标准方程就可以得出。于是乎这些不等式就可以转化为一些半平面,求的就是半平面交。
而半平面交不可能交出凹多边形(因为凹多边形的定义是有一条边所在的直线能把该多边形分成若干块。。。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]凸多边形 半平面交的更多相关文章
- BZOJ2618[Cqoi2006]凸多边形——半平面交
题目描述 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. 输入 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形.第 ...
- 【bzoj2618】[Cqoi2006]凸多边形 半平面交
题目描述 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. 输入 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形.第 ...
- P4196 [CQOI2006]凸多边形 半平面交
\(\color{#0066ff}{题目描述}\) 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. \(\color{#0066f ...
- luogu4196 [CQOI2006]凸多边形 半平面交
据说pkusc出了好几年半平面交了,我也来水一发 ref #include <algorithm> #include <iostream> #include <cstdi ...
- POJ3525 半平面交
题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似 ...
- bzoj 4445 小凸想跑步 - 半平面交
题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...
- 【kuangbin专题】计算几何_半平面交
1.poj3335 Rotating Scoreboard 传送:http://poj.org/problem?id=3335 题意:就是有个球场,球场的形状是个凸多边形,然后观众是坐在多边形的边上的 ...
- bzoj 3190 赛车 半平面交
直接写的裸的半平面交,已经有点背不过模板了... 这题卡精度,要用long double ,esp设1e-20... #include<iostream> #include<cstd ...
- BZOJ 4445 [Scoi2015]小凸想跑步:半平面交
传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...
随机推荐
- 最简单实现跨域的方法:用 Nginx 反向代理
本文作者: 伯乐在线 - 良少 .未经作者许可,禁止转载!欢迎加入伯乐在线 专栏作者. 什么是跨域 跨域,指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascrip ...
- A Tour of Go If and else
Variables declared inside an if short statement are also available inside any of the else blocks. pa ...
- 10670 Work Reduction (贪心 + 被题意坑了- -)y
Problem C: Work Reduction Paperwork is beginning to pile up on your desk, and tensions at the workpl ...
- input输入框默认文字,点击消失
<input type="text" value="请输入用户名" onfocus="if(value=='请输入用户名') {value='' ...
- PTA 5-12 排序 (25分)
给定NN个(长整型范围内的)整数,要求输出从小到大排序后的结果. 本题旨在测试各种不同的排序算法在各种数据情况下的表现.各组测试数据特点如下: 数据1:只有1个元素: 数据2:11个不相同的整数,测试 ...
- 关于lab4实验git+近期出国手续办理
1.下载mit jos lab4时遇到问题(关于git操作,使用,还需进一步理解) 遇到的问题 出现未合并(merge)完全的问题,操作:git add kern/init.c 之后在确认提交 方法二 ...
- JavaScript的递归之更多例子
更多例子 第二个递归的例子是求两个自然数的最大公约数(有没有回到令人怀念的中学时代).下面的程序用的是经典的辗转相除法. //greatest common divisor //假定a.b都是正整数 ...
- android系统架构图
android的系统架构和其操作系统一样,采用了分层的架构.从架构图看,android分为四个层,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和Linux核心层. 1.应用程序 Andr ...
- 进程控制之waitid函数
Single UNIX Specification的XSI扩展包括了另一个取进程终止状态的函数--waitid,此函数类似于waitpid,但提供了更多的灵活性. #include <sys/w ...
- Apache【第一篇】安装
一.简介 Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广泛使用,是最流行的Web ...