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 $ 编号. ...
随机推荐
- HW2.4
import java.util.Scanner; public class Solution { public static void main(String[] args) { final dou ...
- POJ2299: Ultra-QuickSort-合并排序解决逆序数问题
#include<iostream> #include<malloc.h> using namespace std; long long ans; void merge(int ...
- 委托demo
delegate bool Filter(string s); class test { static void Main() { Filter f=new Filter(A); Display(ne ...
- poj1637--Sightseeing tour(最大流)
最大流求混合图是否存在欧拉回路. 以下内容摘自http://www.cnblogs.com/Missa/archive/2012/12/05/2803107.html 讲的很清楚. 混合图的欧拉回路问 ...
- poj1515--Street Directions(边的双连通)
给一个无向图,要求变成强连通的有向图,需要保留哪些边. 边的双连通,对于桥保留两条边,其他的只保留一条边.求双连通的过程中记录保留边. /******************************* ...
- XXX 用户 is not in the sudoers file. This incident will be reported 的问题解决方案
说的是,这种问题,是出现在ubuntu系统里. root@SparkSingleNode:/usr/local/jdk# pwd /usr/local/jdk root@SparkSingleNode ...
- Sublime Text 教程
编辑器的选择(Editor Choices) 从初学编程到现在,我用过的编辑器有EditPlus.UltraEdit.Notepad++.Vim.TextMate和Sublime Text,如果让我从 ...
- hdoj 1231 最大连续子序列
最大连续子序列 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- 多目标遗传算法 ------ NSGA-II (部分源码解析) 临时种群生成新父代种群 fillnds.c
/* Nond-domination based selection routines */ # include <stdio.h> # include <stdlib.h> ...
- iOS开发 落地消息多的处理办法(仅供参考)
1.首先要知道一点,你的消息储存是用数据库储存的! 看了一下微信和qq的消息处理,一般情况下第三方(亲加,容云,环信都会有本地的数据库)处理过的! 但是我发现,最近一个需求要求开发@"消息已 ...