欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ2618


题意概括

  给出多个凸包,求面积交。


题解

  首先我们考虑两个凸包相交的情况。

  例题:HDU1632

  我们可以证明,两个凸包相交,如果面积交为正,那么新构成的面积块一定也是一个凸包。

  具体证明可以分情况讨论,反正画几个图就明白了。也可以网上查一查。

  那么题目就简单了。

  变成了一道水水的码农题。

  两个凸包面积交之后,还是凸包,所以,题目就变成了依次进行面积交。

  只需要考虑两个凸包相交的情况。

  构成的新凸包上的顶点只有可能是两类:

  1.  原来两个凸包的某一个的顶点,并且处于另一个凸包内。

  2.  原来两个凸包的交点。

  那么只需要最暴力的揪出这些点就可以了。

  判断一个点是否在里面,可以用面积法。

  当然网上有很多其他的方法。

  求线段交点,方法就很多了。一搜一大堆的。


代码

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
const double Eps=1e-8;
int Dcmp(double a){
if (fabs(a)<Eps)
return 0;
return a<0?-1:1;
}
int Dcmp(double x,double y){
return Dcmp(x-y);
}
struct Point{
double x,y;
Point (){}
Point (double x_,double y_){
x=x_,y=y_;
}
Point operator + (Point a){
return Point(x+a.x,y+a.y);
}
Point operator - (Point a){
return Point(x-a.x,y-a.y);
}
Point operator * (double a){
return Point(x*a,y*a);
}
Point operator / (double a){
return Point(x/a,y/a);
}
};
double cross(Point a,Point b){
return a.x*b.y-a.y*b.x;
}
double cross(Point a,Point b,Point c){
return cross(b-a,c-a);
}
double Dot(Point a,Point b){
return a.x*b.x+a.y*b.y;
}
double dis(Point a,Point b){
return sqrt(Dot(a-b,a-b));
}
Point readPoint(){
double x,y;
scanf("%lf%lf",&x,&y);
return Point(x,y);
}
struct Line{
Point a,b;
Line (){}
Line (Point x,Point y){
a=x,b=y;
}
};
bool Lcross(Line L1,Line L2){
return Dcmp(cross(L1.a,L2.a,L2.b))*Dcmp(cross(L1.b,L2.a,L2.b))<0;
}
bool crossed(Line L1,Line L2){
return Lcross(L1,L2)&&Lcross(L2,L1);
}
Point Cross_Point(Line a,Line b){
Point P=a.a,Q=b.a,v=a.b-a.a,w=b.b-b.a,u=P-Q;
double t=cross(w,u)/cross(v,w);
return P+v*t;
}
Point O;
bool cmpAngle(Point a,Point b){
double cr=cross(O,a,b);
if (Dcmp(cr)==0)
return dis(O,a)<dis(O,b);
return cr>0;
}
struct Ploygon{
static const int M=600;
int m;
Point P[M];
double Area;
void clear(){
m=0;
Area=-1;
}
void add(Point x){
for (int i=1;i<=m;i++)
if (Dcmp(x.x,P[i].x)==0&&Dcmp(x.y,P[i].y)==0)
return;
P[++m]=x;
}
bool cmpO(Point a,Point b){
if (Dcmp(a.y,b.y)==0)
return Dcmp(a.x,b.x)<=0;
return Dcmp(a.y,b.y)<0;
}
void buildPloygon(){
int st[M],top=0;
O=P[1];
for (int i=2;i<=m;i++)
if (!cmpO(O,P[i]))
O=P[i];
sort(P+1,P+m+1,cmpAngle);
st[++top]=1,st[++top]=2;
for (int i=3;i<=m;i++){
while (top>=2&&Dcmp(cross(P[st[top-1]],P[st[top]],P[i]))<0)
top--;
st[++top]=i;
}
for (int i=1;i<=top;i++)
P[i]=P[st[i]];
m=top;
}
double area(){
if (Dcmp(Area,-1)!=0)
return Area;
Area=0;
for (int i=2;i<m;i++)
Area+=fabs(cross(P[1],P[i],P[i+1]));
Area/=2;
return Area;
}
bool inside(Point x){
double ar=0;
for (int i=1;i<=m;i++)
ar+=fabs(cross(x,P[i],P[i%m+1]));
ar/=2;
return Dcmp(area(),ar)==0;
}
}P1,P2,P3;
int n,m;
int main(){
scanf("%d",&n);
for (int cnt=1;cnt<=n;cnt++){
P2.clear();
scanf("%d",&m);
while (m--)
P2.add(readPoint());
P2.buildPloygon();
if (cnt==1){
P1=P2;
continue;
}
P3.clear();
for (int i=1;i<=P1.m;i++)
if (P2.inside(P1.P[i]))
P3.add(P1.P[i]);
for (int i=1;i<=P2.m;i++)
if (P1.inside(P2.P[i]))
P3.add(P2.P[i]);
for (int i=1;i<=P1.m;i++)
for (int j=1;j<=P2.m;j++){
Line L1=Line(P1.P[i],P1.P[i%P1.m+1]),L2=Line(P2.P[j],P2.P[j%P2.m+1]);
if (crossed(L1,L2))
P3.add(Cross_Point(L1,L2));
}
P3.buildPloygon();
if (Dcmp(P3.area())==0){
printf("0.000");
return 0;
}
P1=P3;
}
printf("%.3lf",P1.area());
return 0;
}

  

BZOJ2618 [Cqoi2006]凸多边形 凸包 计算几何的更多相关文章

  1. bzoj2618: [Cqoi2006]凸多边形

    Description 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. Input 第一行有一个整数n,表示凸多边形的个数,以下依 ...

  2. bzoj2618[Cqoi2006]凸多边形 半平面交

    这是一道半平面交的裸题,第一次写半平面交,就说一说我对半平面交的理解吧. 所谓半平面交,就是求一大堆二元一次不等式的交集,而每个二元一次不等式的解集都可以看成是在一条直线的上方或下方,联系直线的标准方 ...

  3. BZOJ2618[Cqoi2006]凸多边形——半平面交

    题目描述 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. 输入 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形.第 ...

  4. 【半平面交】bzoj2618 [Cqoi2006]凸多边形

    #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ...

  5. BZOJ-2618 [CQOI2006]凸多边形

    半平面交模版题.. #include <cstdlib> #include <cstdio> #include <cmath> #include <cstri ...

  6. 【BZOJ2618】[CQOI2006]凸多边形(半平面交)

    [BZOJ2618][CQOI2006]凸多边形(半平面交) 题面 BZOJ 洛谷 题解 这个东西就是要求凸多边形的边所形成的半平面交. 那么就是一个半平面交模板题了. 这里写的是平方的做法. #in ...

  7. 【BZOJ-2618】凸多边形 计算几何 + 半平面交 + 增量法 + 三角剖分

    2618: [Cqoi2006]凸多边形 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 959  Solved: 489[Submit][Status] ...

  8. 【BZOJ 2618】 2618: [Cqoi2006]凸多边形 (半平面交)

    2618: [Cqoi2006]凸多边形 Description 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. Input 第一 ...

  9. bzoj 2618 2618: [Cqoi2006]凸多边形(半平面交)

    2618: [Cqoi2006]凸多边形 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 656  Solved: 340[Submit][Status] ...

随机推荐

  1. TCP/IP详解 卷1 第十九章 TCP的交互数据流

    19.1 引言 成块数据:比如ftp.电子邮件.Usenet新闻 交互数据:Telnet.Rlogin 成块数据的报文段基本上都是满长度(full-size)的,而交互数据小的多(Telnet和Rlo ...

  2. 2017-2018-2 20155303『网络对抗技术』Exp9:Web安全基础

    2017-2018-2 『网络对抗技术』Exp9:Web安全基础 --------CONTENTS-------- 一.基础问题回答 1.SQL注入攻击原理,如何防御? 2.XSS攻击的原理,如何防御 ...

  3. 【ANT】ant使用

    官网:https://ant.apache.org/,task介绍:https://ant.apache.org/manual/index.html 0.介绍: Ant的构建文件当开始一个新的项目时, ...

  4. 【API】检查进程是否存在 - CreateToolhelp32Snapshot

    1 学习目标 今天静态逆向mydocument病毒时,看到病毒代码为了防止自身被调试会先检测杀毒软件和调试工具的进程是否存在.如果没有杀毒软件则释放真正的病毒文件,提前熟悉一下枚举进程的反汇编代码. ...

  5. Statistics in Python

    Statistics in Python Materials for the “Statistics in Python” euroscipy 2015 tutorial. Requirements ...

  6. freeRTOS中文实用教程3--中断管理之中断嵌套

    1.前言 最新的 FreeRTOS 移植中允许中断嵌套.中断嵌套需要在 FreeRTOSConfig.h 中设置configKERNEL_INTERRUPT_PRIORITY 和configMAX_S ...

  7. win7下出现读不到移动硬盘的解决办法

    很多电脑会出现移动硬盘读不到,或者 读到部分盘的情况,那么下面我就为大家来一一解决这些情况: 方法一:    最常见的是硬盘供电不足导致 ,要么换一个硬盘盒子,要么给硬盘一个外加电源即可方法二:    ...

  8. Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析【转】

    转自:http://blog.csdn.net/hzn407487204/article/details/7995041 在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设 ...

  9. springboot系列十四、自定义实现starter

    一.starter的作用 当我们实现了一个组建,希望尽可能降低它的介入成本,一般的组建写好了,只要添加spring扫描路径加载spring就能发挥作用.有个更简单的方式扫描路径都不用加,直接引入jar ...

  10. 安装java时,配置环境变量classpath的作用

    想必大家在安装javaSE或其它版本时会注意到,在配置环境变量path之后,还需要新建一个名为CLASSPATH,变量值设为 .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt. ...