bzoj 2618 半平面交模板+学习笔记
题目大意
给你n个凸多边形,求多边形的交的面积
分析
题意\(=\)给你一堆边,让你求半平面交的面积
做法
半平面交模板
1.定义半平面为向量的左侧
2.将所有向量的起点放到一个中心,以中心参照进行逆时针极角排序
但是直接按叉积排序会转圈圈
于是我们从\(x\)轴负半轴开始逆时针旋转,将坐标轴分为上下两部(\(x\)轴属于下部)
当两个向量终点的\(y\)都在x轴上时,按x从小到大排
当两个向量终点同在上部/同在下部时,按叉积排(平行按左右排)
当一上一下时,下部的排前
注意:快排时像我这样贪方便,在cmp里swap一下想都不想的人也是很罕见的
3.考虑下面这样一幅图

黑色为原半平面交的边界,蓝色为新加入的向量
不难发现当之前交点在蓝色右边时,向量1要被删掉
这样的话,每次新加入向量,就会删掉在向量右边的交点(线上的也要删)
最后会在所有交点的右边,画幅图出来发现这和凸包是非常像的
然后考虑下面的一幅图

发现我们维护的凸包首尾都是要删除的
所以我们要写一个双端队列
4.考虑平行的两个向量,一定是保留最左的一个
5.考虑下面这幅图

图上的边搞完之后都还是在双端队列里的
但是:最后带红色标记的那一条边是无效的,为什么呢?
因为凸包首尾是连起来的!
所以最后还要模拟插入队头,把队尾中多余的半平面去掉
6.如果题目没有保证半平面封闭,就加上一个超大的四边形限制
推广
uoj的一篇博客写的很棒,证明也很棒,还提到了一种先求上凸壳,再求下凸壳,再把两边多出来的部分删掉的方法 搓这
solution
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
typedef double db;
const int M=507;
inline int rd(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
}
int n,m,tt;
struct pt{
db x,y;
pt(db xx=0,db yy=0){x=xx;y=yy;}
}p[M],a[M];
pt operator +(pt x,pt y){return pt(x.x+y.x,x.y+y.y);}
pt operator -(pt x,pt y){return pt(x.x-y.x,x.y-y.y);}
pt operator *(pt x,db d){return pt(x.x*d,x.y*d);}
pt operator /(pt x,db d){return pt(x.x/d,x.y/d);}
db slop(pt x){return x.y/x.x;}
db dot(pt x,pt y){return x.x*y.x+x.y*y.y;}
db det(pt x,pt y){return x.x*y.y-x.y*y.x;}
db len(pt x){return sqrt(dot(x,x));}
db dis(pt x,pt y){return len(y-x);}
db area(pt x,pt y,pt z){return det(y-x,z-x);}
struct line{
pt P,v;
line(pt PP=pt(),pt vv=pt()){P=PP;v=vv;}
}l[M],s[M];
pt inter(line x,line y){
pt u=x.P-y.P;
db t=det(u,y.v)/det(y.v,x.v);
return x.P+x.v*t;
}
bool parallel(line x,line y){return det(y.v,x.v)==0;}
bool lineleft(line x,line y){
db tp=det(x.v,y.v);
return (tp>0)||((tp==0)&&det(x.v,y.P-x.P)>0);
}
bool ptright(pt x,line y){return det(y.v,x-y.P)<=0;}///<=
bool cmp(line x,line y){//极角排序
if(x.v.y==0 && y.v.y==0) return x.v.x<y.v.x;//y都为0
if(x.v.y<=0 && y.v.y<=0) return lineleft(x,y);//同在上部
if(x.v.y>0 && y.v.y>0 ) return lineleft(x,y);//同在下部
return x.v.y<y.v.y;//一上一下
}
void hpi(){//half-plane intersection
sort(l+1,l+m+1,cmp);//sort
int tp=0,i;
for(i=1;i<=m;i++){
if(i==1||!parallel(l[i],l[i-1])) tp++;//平行特判
l[tp]=l[i];
}
m=tp;
int L=1,R=2;
s[1]=l[1],s[2]=l[2];
for(i=3;i<=m;i++){
while(L<R && ptright(inter(s[R],s[R-1]),l[i])) R--;
while(L<R && ptright(inter(s[L],s[L+1]),l[i])) L++;
s[++R]=l[i];
}
while(L<R && ptright(inter(s[R],s[R-1]),s[L])) R--;//最后删除无用平面
if(R-L<=1){//若半平面交退化为点或线
puts("0.000");
return;
}
tp=0;
s[L-1]=s[R];
for(i=L;i<=R;i++) a[++tp]=inter(s[i],s[i-1]);//求出相邻两边的交点,转化为凸包的记录方法
db ans=0;
for(i=3;i<=tp;i++) ans+=area(a[1],a[i-1],a[i])*0.5;
printf("%.3lf",ans);//求面积
}
int main(){
int i,x,y,z,st;
tt=rd();
n=m=0;
while(tt--){
z=rd();
st=n+1;
while(z--){
x=rd(),y=rd();
p[++n]=pt(x,y);
if(n>st) l[++m]=line(p[n-1],p[n]-p[n-1]);
}
l[++m]=line(p[n],p[st]-p[n]);
}
hpi();
return 0;
}
bzoj 2618 半平面交模板+学习笔记的更多相关文章
- POJ 3525 /// 半平面交 模板
题目大意: 给定n,接下来n行逆时针给定小岛的n个顶点 输出岛内离海最远的点与海的距离 半平面交模板题 将整个小岛视为由许多半平面围成 那么以相同的比例缩小这些半平面 一直到缩小到一个点时 那个点就是 ...
- bzoj 2618【半平面交模板】
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> usin ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- 半平面交模板(O(n*n)&& O(n*log(n))
摘自http://blog.csdn.net/accry/article/details/6070621 首先解决问题:什么是半平面? 顾名思义,半平面就是指平面的一半,我们知道,一条直线可以将平面分 ...
- POJ 半平面交 模板题 三枚
给出三个半平面交的裸题. 不会的上百度上谷(gu)歌(gou)一下. 毕竟学长的语文是体育老师教的.(卡格玩笑,别当真.) 这种东西明白就好,代码可以当模板. //poj1474 Video Surv ...
- 再来一道测半平面交模板题 Poj1279 Art Gallery
地址:http://poj.org/problem?id=1279 题目: Art Gallery Time Limit: 1000MS Memory Limit: 10000K Total Su ...
- C++模板学习笔记
一个有趣的东西:实现一个函数print, 输入一个数组, 输出数组的各个维度长度. eg. ], b[][], c[][][]; print(a); //(2, 4) print(b); //(3, ...
- 初步C++类模板学习笔记
类模板 实现:在上课时间的定义给它的一个或多个参数,这些参数代表了不同的数据类型. -->抽象的类. 在调用类模板时, 指定參数, 由编 ...
- tornada模板学习笔记
import tornado.web import tornado.httpserver import tornado.ioloop import tornado.options import os. ...
随机推荐
- elasticsearch-dsl聚合-2
接续上篇,本篇介绍elasticsearch聚合查询,使用python库elasticsearch-dsl进行聚合查询操作. 条形图 聚合有一个令人激动的特性就是能够十分容易地将数据转换成图表和图形. ...
- 基于mybatis设计简单信息管理系统1
驼峰式命名法 骆驼式命名法就是当变量名或函数名是由一个或多个单词连结在一起,而构成的唯一识别字时,第一个单词以小写字母开始:第二个单词的首字母大写或每一个单词的首字母都采用大写字母,例如:myFirs ...
- Linux - 用户环境变量的查看与设置
1. 查看当前有哪些环境变量 直接输入命令:env 2. 设置用户环境变量 输入命令:vim ~/.bash_profile,打开文件,输入如下内容: 范例(设置maven环境变量): export ...
- 7-4 python 接口开发(提供mock服务)
1.登录接口开发(数据存在数据库中) 接口开发做mock(模拟功能) tools.py import pymysql def my_db(sql): conn = pymysql.connect(h ...
- HttpServletRequest cannot be resolved to a type The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
HttpServletRequest cannot be resolved to a type The superclass "javax.servlet.http.HttpServlet& ...
- Python__关于列表的引用 以append操作为例
对于列表这样的可变类型来说,对它操作是不会改变内存地址的. 若列表里面存的元素是整数这样的不可变类型,若修改这个元素那地址还是会改变,如: >>> a = [,,] >> ...
- 关于TP3.2框架读取Sql server中文字段数据以及处理乱码的一些小心得
最近要做一个项目,需要使用TP3.2框架,之前什么也不会,就硬着头皮上了,结果真的闹了挺多emmmmmm挺低级的错误,就像SQL Server中文字段的读取,一开始我是照着读取英文字段的格式来写的,在 ...
- 小程序里面使用wxParse解析富文本导致页面空白等
在部分安卓手机上会出现白屏的情况且有些ios手机上图文混排上,图片显示不出问题 解决:把插件里面的console.dir去掉即可(原因在于安卓手机无法解析console.dir) 有些图片解析出来下面 ...
- mysql8.0 忘记root密码
先打开一个cmd:net stop mysql //关闭mysql服务mysqld --shared-memory --skip-grant-tables//跳过登录密码在不关闭第一个CMD的情况下打 ...
- openwrt(二) 配置openwrt及编译
导航 1. 配置openwrt 2. 编译openwrt 3. 错误记录 1. 配置openwrt 在openwrt的根目录下,执行make menuconfig. 这个界面我也只是了解了这两个选项而 ...