题目大意

给你n个凸多边形,求多边形的交的面积

分析

题意\(=\)给你一堆边,让你求半平面交的面积

做法

半平面交模板

1.定义半平面为向量的左侧

2.将所有向量的起点放到一个中心,以中心参照进行逆时针极角排序

但是直接按叉积排序会转圈圈

于是我们从\(x\)轴负半轴开始逆时针旋转,将坐标轴分为上下两部(\(x\)轴属于下部)

当两个向量终点的\(y\)都在x轴上时,按x从小到大排

当两个向量终点同在上部/同在下部时,按叉积排(平行按左右排)

当一上一下时,下部的排前

注意:快排时像我这样贪方便,在cmp里swap一下想都不想的人也是很罕见的

3.考虑下面这样一幅图



黑色为原半平面交的边界,蓝色为新加入的向量

不难发现当之前交点在蓝色右边时,向量1要被删掉

这样的话,每次新加入向量,就会删掉在向量右边的交点(线上的也要删)

最后会在所有交点的右边,画幅图出来发现这和凸包是非常像的

然后考虑下面的一幅图



发现我们维护的凸包首尾都是要删除的

所以我们要写一个双端队列

4.考虑平行的两个向量,一定是保留最左的一个

5.考虑下面这幅图



图上的边搞完之后都还是在双端队列里的

但是:最后带红色标记的那一条边是无效的,为什么呢?

因为凸包首尾是连起来的!

所以最后还要模拟插入队头,把队尾中多余的半平面去掉

6.如果题目没有保证半平面封闭,就加上一个超大的四边形限制

推广

uoj的一篇博客写的很棒,证明也很棒,还提到了一种先求上凸壳,再求下凸壳,再把两边多出来的部分删掉的方法   搓这

solution

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cctype>
  5. #include <cmath>
  6. #include <algorithm>
  7. using namespace std;
  8. typedef double db;
  9. const int M=507;
  10. inline int rd(){
  11. int x=0;bool f=1;char c=getchar();
  12. for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
  13. for(;isdigit(c);c=getchar()) x=x*10+c-48;
  14. return f?x:-x;
  15. }
  16. int n,m,tt;
  17. struct pt{
  18. db x,y;
  19. pt(db xx=0,db yy=0){x=xx;y=yy;}
  20. }p[M],a[M];
  21. pt operator +(pt x,pt y){return pt(x.x+y.x,x.y+y.y);}
  22. pt operator -(pt x,pt y){return pt(x.x-y.x,x.y-y.y);}
  23. pt operator *(pt x,db d){return pt(x.x*d,x.y*d);}
  24. pt operator /(pt x,db d){return pt(x.x/d,x.y/d);}
  25. db slop(pt x){return x.y/x.x;}
  26. db dot(pt x,pt y){return x.x*y.x+x.y*y.y;}
  27. db det(pt x,pt y){return x.x*y.y-x.y*y.x;}
  28. db len(pt x){return sqrt(dot(x,x));}
  29. db dis(pt x,pt y){return len(y-x);}
  30. db area(pt x,pt y,pt z){return det(y-x,z-x);}
  31. struct line{
  32. pt P,v;
  33. line(pt PP=pt(),pt vv=pt()){P=PP;v=vv;}
  34. }l[M],s[M];
  35. pt inter(line x,line y){
  36. pt u=x.P-y.P;
  37. db t=det(u,y.v)/det(y.v,x.v);
  38. return x.P+x.v*t;
  39. }
  40. bool parallel(line x,line y){return det(y.v,x.v)==0;}
  41. bool lineleft(line x,line y){
  42. db tp=det(x.v,y.v);
  43. return (tp>0)||((tp==0)&&det(x.v,y.P-x.P)>0);
  44. }
  45. bool ptright(pt x,line y){return det(y.v,x-y.P)<=0;}///<=
  46. bool cmp(line x,line y){//极角排序
  47. if(x.v.y==0 && y.v.y==0) return x.v.x<y.v.x;//y都为0
  48. if(x.v.y<=0 && y.v.y<=0) return lineleft(x,y);//同在上部
  49. if(x.v.y>0 && y.v.y>0 ) return lineleft(x,y);//同在下部
  50. return x.v.y<y.v.y;//一上一下
  51. }
  52. void hpi(){//half-plane intersection
  53. sort(l+1,l+m+1,cmp);//sort
  54. int tp=0,i;
  55. for(i=1;i<=m;i++){
  56. if(i==1||!parallel(l[i],l[i-1])) tp++;//平行特判
  57. l[tp]=l[i];
  58. }
  59. m=tp;
  60. int L=1,R=2;
  61. s[1]=l[1],s[2]=l[2];
  62. for(i=3;i<=m;i++){
  63. while(L<R && ptright(inter(s[R],s[R-1]),l[i])) R--;
  64. while(L<R && ptright(inter(s[L],s[L+1]),l[i])) L++;
  65. s[++R]=l[i];
  66. }
  67. while(L<R && ptright(inter(s[R],s[R-1]),s[L])) R--;//最后删除无用平面
  68. if(R-L<=1){//若半平面交退化为点或线
  69. puts("0.000");
  70. return;
  71. }
  72. tp=0;
  73. s[L-1]=s[R];
  74. for(i=L;i<=R;i++) a[++tp]=inter(s[i],s[i-1]);//求出相邻两边的交点,转化为凸包的记录方法
  75. db ans=0;
  76. for(i=3;i<=tp;i++) ans+=area(a[1],a[i-1],a[i])*0.5;
  77. printf("%.3lf",ans);//求面积
  78. }
  79. int main(){
  80. int i,x,y,z,st;
  81. tt=rd();
  82. n=m=0;
  83. while(tt--){
  84. z=rd();
  85. st=n+1;
  86. while(z--){
  87. x=rd(),y=rd();
  88. p[++n]=pt(x,y);
  89. if(n>st) l[++m]=line(p[n-1],p[n]-p[n-1]);
  90. }
  91. l[++m]=line(p[n],p[st]-p[n]);
  92. }
  93. hpi();
  94. return 0;
  95. }

bzoj 2618 半平面交模板+学习笔记的更多相关文章

  1. POJ 3525 /// 半平面交 模板

    题目大意: 给定n,接下来n行逆时针给定小岛的n个顶点 输出岛内离海最远的点与海的距离 半平面交模板题 将整个小岛视为由许多半平面围成 那么以相同的比例缩小这些半平面 一直到缩小到一个点时 那个点就是 ...

  2. bzoj 2618【半平面交模板】

    #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> usin ...

  3. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  4. 半平面交模板(O(n*n)&& O(n*log(n))

    摘自http://blog.csdn.net/accry/article/details/6070621 首先解决问题:什么是半平面? 顾名思义,半平面就是指平面的一半,我们知道,一条直线可以将平面分 ...

  5. POJ 半平面交 模板题 三枚

    给出三个半平面交的裸题. 不会的上百度上谷(gu)歌(gou)一下. 毕竟学长的语文是体育老师教的.(卡格玩笑,别当真.) 这种东西明白就好,代码可以当模板. //poj1474 Video Surv ...

  6. 再来一道测半平面交模板题 Poj1279 Art Gallery

    地址:http://poj.org/problem?id=1279 题目: Art Gallery Time Limit: 1000MS   Memory Limit: 10000K Total Su ...

  7. C++模板学习笔记

    一个有趣的东西:实现一个函数print, 输入一个数组, 输出数组的各个维度长度. eg. ], b[][], c[][][]; print(a); //(2, 4) print(b); //(3, ...

  8. 初步C++类模板学习笔记

    类模板 实现:在上课时间的定义给它的一个或多个参数,这些参数代表了不同的数据类型.                              -->抽象的类. 在调用类模板时, 指定參数, 由编 ...

  9. tornada模板学习笔记

    import tornado.web import tornado.httpserver import tornado.ioloop import tornado.options import os. ...

随机推荐

  1. django连接mysql数据库配置,出现no module named mysqldb报错

    作为一个菜鸟运维也是要有梦想的,万一学会了python走向人生巅峰了呢.好吧,都是瞎想,今天主要介绍下django配置,最近也开始摸索这个牛b框架了,当然大佬肯定不屑一顾,都是照顾照顾我们这些菜鸟初学 ...

  2. Ansible学习 Patterns

    Ansible中ad-hoc命令格式如下:ansible <pattern_goes_here> -m <module_name> -a <arguments>,P ...

  3. dts--tests(四)

    unit_tests.py """ DPDK Test suite. This TestSuite runs the unit tests included in DPD ...

  4. Linux下 VI 编辑器操作

    VI编辑器的三种模式:命令模式.输入模式.末行模式. 1.命令模式:vi启动后默认进入的是命令模式,从这个模式使用命令可以切换到另外两种模式,同时无论在何种模式下,[Esc]键都可以回到命令模式.在命 ...

  5. MySQL的隐式类型转换整理总结

    当我们对不同类型的值进行比较的时候,为了使得这些数值「可比较」(也可以称为类型的兼容性),MySQL会做一些隐式转化(Implicit type conversion). 比如下面的例子:   1 2 ...

  6. 邮件系统之Postfix与Dovecot

    电子邮件系统 电子邮件系统基于邮件协议来完成电子邮件的传输,常见的邮件协议有: 简单邮件传输协议(Simple Mail Transfer Protocol,SMTP):用于发送和中转发出的电子邮件, ...

  7. AD高级规则设置

    inpolygon 是所有的覆铜 ispad 是焊盘到焊盘的间距 IsVia 过孔间距 ispad and InComponent('S1')    设置某个器件的焊盘间距规则 ispad and H ...

  8. LinkedHashMap和HashMap的比较使用 详解

    由于现在项目中用到了LinkedHashMap,并不是太熟悉就到网上搜了一下. import java.util.HashMap; import java.util.Iterator; import ...

  9. cjson 增强对逗号处理

    https://sourceforge.net/projects/cjson/ 解析JSON比较好的轻量级工具,使用比较方便,今天测试发现有些JSON解析失败,但其他工具可以正常解析. 跟踪发现是cJ ...

  10. 自己定义的TryParse()

    out 参数的练习,自己定义的TryParse()... 一开始写错了,错在:判断str[i] >= '0'&& str[i]<='9'时,把str[i]当数字去判断了.. ...