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 $ 编号. ...
随机推荐
- AJAX中文乱码PHP完美解决(IE和Firefox兼容)
最近在做一个项目,遇到AJAX中文乱码问题,经过一个下午的努力终于完美解决,现将心得写下来,希望对那些还困绕在这个问题而头痛不已的人们有所帮助. 众所周知,使用AJAX传送和接收中文参数时,如果不在客 ...
- zoj 3460 Missile【经典建图&&二分】
Missile Time Limit: 2 Seconds Memory Limit: 65536 KB You control N missile launching towers. Ev ...
- PAT 1003. Emergency (25)
1003. Emergency (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue As an emerg ...
- iOS开发中使用CIDetector检测人脸
在iOS5 系统中,苹果就已经有了检测人脸的api,能够检测人脸的位置,包括左右眼睛,以及嘴巴的位置,返回的信息是每个点位置.在 iOS7中,苹果又加入了检测是否微笑的功能.通过使用 CIDetect ...
- jitsi
http://code.csdn.net/openkb/p-Jitsi https://download.jitsi.org/jitsi/nightly/ https://download.jitsi ...
- 知识点整理之Java的Cookie操作
创建Cookie // new一个Cookie对象,键值对为参数 Cookie cookie = new Cookie("key", "value"); // ...
- TCP/IP 中的二进制反码求和算法
对于这个算法,很多书上只是说一下思路,没有具体的实现.我在这里举个例子吧 以4bit(计算方便一点,和16bit是一样的)做检验和来验证. 建设原始数据为 1100 , 1010 , 0000(校验位 ...
- 关于ProgressBar的美化问题
Android自带的ProgressBar其实也算不上丑陋,但是如果所有的App都使用一个模式的ProgressBar,那么估计用户就要崩溃了,打开任何一个App,擦,进度条都一模一样..有鉴于此,我 ...
- virtualization-vs-containerization
http://containerz.blogspot.com/2015/03/virtualization-vs-containerization.html Virtualization vs. Co ...
- 使用Spring Boot快速构建应用
http://www.infoq.com/cn/news/2014/01/spring-boot/ 随着Spring 4新版本的发布,Spring Boot这个新的子项目得到了广泛的关注,因为不管是S ...