2618: [Cqoi2006]凸多边形

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 959  Solved: 489
[Submit][Status][Discuss]

Description

逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
 

则相交部分的面积为5.233。

Input

第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。

Output

输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。

Sample Input

2
6
-2 0
-1 -2
1 -2
2 0
1 2
-1 2
4
0 -3
1 -1
2 2
-1 0

Sample Output

5.233

HINT

100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数

Source

Solution

裸半平面交

这里用的O(n^{2})的增量法,求完半平面交后再求多边形面积就好了,三角剖分一下就可以

一个不错的讲解

具体的做法:

•初始化时加上一个范围巨大的“框”
•每次拿一个新的半平面切割原先的凸集
•保留在新加直线左边的点,删除右边的,有向直线与多边形相交产生的新的点加入到新多边形内

Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<cstdlib>
using namespace std;
struct Vector
{
double x,y;
Vector(double X=,double Y=) {x=X,y=Y;}
};
typedef Vector Point;
typedef vector<Point> Polygon;
Polygon polygon;
#define MAXN 20
#define MAXM 100
Point P[MAXN][MAXM];
#define eps 1e-8
#define INF 1000
const double pi= acos(-1.0);
Vector operator + (Vector A,Vector B) {return ((Vector){A.x+B.x,A.y+B.y});}
Vector operator - (Vector A,Vector B) {return ((Vector){A.x-B.x,A.y-B.y});}
Vector operator * (Vector A,double p) {return ((Vector){A.x*p,A.y*p});}
Vector operator / (Vector A,double p) {return ((Vector){A.x/p,A.y/p});}
int dcmp(double x) {if(fabs(x)<eps) return ; else return x<? -:;}
bool operator == (const Vector& a,const Vector& b) {return dcmp(a.x-b.x)==&&dcmp(a.y-b.y)==;}
double Dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;}
double Len(Vector A) {return sqrt(Dot(A,A));}
double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
Point GLI(Point P,Vector v,Point Q,Vector w) {Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return P+v*t;}
double DisTL(Point P,Point A,Point B) {Vector v1=B-A,v2=P-A; return fabs(Cross(v1,v2)/Len(v1));}
bool OnSegment(Point P,Point A,Point B) {return dcmp(DisTL(P,A,B))==&&dcmp(Dot(P-A,P-B))<&&!(P==A)&&!(P==B);}
double PolygonArea(Polygon p)
{
double area=;
int n=p.size();
for(int i=;i<n-;i++)
area+=Cross(p[i]-p[],p[i+]-p[]);
return area/;
}
Polygon CutPolygon(Polygon poly,Point A,Point B)
{
Polygon newpoly;
Point C,D,ip;
int n=poly.size(),i;
for(i=;i<n;i++)
{
C=poly[i];
D=poly[(i+)%n];
if(dcmp(Cross(B-A,C-A))>=)
newpoly.push_back(C);
if(dcmp(Cross(B-A,D-C))!=)
{
ip=GLI(A,B-A,C,D-C);
if(OnSegment(ip,C,D))
newpoly.push_back(ip);
}
}
return newpoly;
}
void InitPolygon(Polygon &poly,double inf)
{
poly.clear();
poly.push_back((Point){-inf,-inf});
poly.push_back((Point){inf,-inf});
poly.push_back((Point){inf,inf});
poly.push_back((Point){-inf,inf});
}
void Debug()
{
for (int j=; j<polygon.size(); j++)
printf("(%.1lf,%.1lf)-->",polygon[j].x,polygon[j].y);
printf("(%.1lf,%.1lf)",polygon[].x,polygon[].y);
puts("");
}
int main()
{
int N,M;
scanf("%d",&N);
InitPolygon(polygon,INF);
for (int i=; i<=N; i++)
{
scanf("%d",&M);
for (int j=; j<=M; j++)
scanf("%lf%lf",&P[i][j].x,&P[i][j].y);
P[i][M+]=P[i][];
for (int j=; j<=M; j++)
{polygon=CutPolygon(polygon,P[i][j],P[i][j+]); /*Debug();*/}
}
printf("%.3lf\n",PolygonArea(polygon));
return ;
}

自己调个模板,p事怎么这么多QAQ

【BZOJ-2618】凸多边形 计算几何 + 半平面交 + 增量法 + 三角剖分的更多相关文章

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

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

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

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

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

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

  4. 2018.07.04 BZOJ 2618 Cqoi2006凸多边形(半平面交)

    2618: [Cqoi2006]凸多边形 Time Limit: 5 Sec Memory Limit: 128 MB Description 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n ...

  5. BZOJ - 2618 凸多边形 (半平面交)

    题意:求n个凸多边形的交面积. 半平面交模板题. #include<bits/stdc++.h> using namespace std; typedef long long ll; ty ...

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

    很明显是一道半平面交的题. 先说一下半平面交的步骤: 1.用点向法(点+向量)表示直线 2.极角排序,若极角相同,按相对位置排序. 3.去重,极角相同的保留更优的 4.枚举边维护双端队列 5.求答案 ...

  7. bzoj 3190 [JLOI2013]赛车 半平面交+细节处理

    题目大意 这里有一场赛车比赛正在进行,赛场上一共有N辆车,分别称为g1,g2--gn.赛道是一条无限长的直线.最初,gi位于距离起跑线前进ki的位置.比赛开始后,车辆gi将会以vi单位每秒的恒定速度行 ...

  8. bzoj 1038 瞭望塔 半平面交+分段函数

    题目大意 给你一座山,山的形状在二维平面上为折线 给出\((x_1,y_1),(x_2,y_2)...(x_n,y_n)\)表示山的边界点或转折点 现在要在\([x_1,x_n]\)(闭区间)中选择一 ...

  9. POJ 3384 Feng Shui(计算几何の半平面交+最远点对)

    Description Feng shui is the ancient Chinese practice of placement and arrangement of space to achie ...

随机推荐

  1. 02Spring_Ioc和DI介绍

    什么是IOC? IoC: 控制反转, 解决程序对象紧密耦合问题(工厂+反射+ 配置文件), 将程序中原来构造对象的权限,交给IoC容器来构造,当程序需要对象,找IoC容器获取.

  2. BZOJ 1014 【JSOI2008】 火星人prefix

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  3. Effective java 第2版 - 笔记(01) 单例(Singleton)的枚举(enum)实现

    直接上代码: public enum Boss { INSTANCE; private String name; public void doSomeThing() { System.out.prin ...

  4. oracle: job使用

    oracle的job,实际上就是数据库内置的定时任务,类似代码中的Timer功能.下面是使用过程: 这里我们模拟一个场景:定时调用存储过程P_TEST_JOB 向表TEST_JOB_LOG中插入数据 ...

  5. 向jboss写入服务器日志

    实际开发中,记录日志是常用的功能,jboss默认情况下已经记录了很多运行日志,如果开发人员要手动在server.log中写入日志,可以参考下面的方法: package utils; import ja ...

  6. node 学习笔记 - Modules 模块加载系统 (2)

    本文同步自我的个人博客:http://www.52cik.com/2015/12/14/learn-node-modules-module.html 上一篇讲了模块是如何被寻找到然后加载进来的,这篇则 ...

  7. 我做PHP,但是我要批判下整天唱衰.NET的淫

    笔者每天都能看到月经贴-".NET已死"!!! 笔者之前一直在CSDN上面写博客,泡论坛,但是有约莫一年来着了发现CSDN上面的博客都没啥更新,CSDN首页推荐的一些文章也没啥新意 ...

  8. [译]用AngularJS构建大型ASP.NET单页应用(二)

    原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single 客 ...

  9. linux | 管道符、输出重定向

    1 输出重定向 ll > a.txt 将 ll的结果写入到a.txt 2 管道符 ls -la | grep h* 这条命令的理解为:ls -la 的结果作为gerp h* 的结果 gerp 是 ...

  10. Collection中list集合的应用常见的方法

    集合 : 用存放对象的容器(集合)     Collection : 跟接口 : 单列集合          ---> List :有序的 ,元素是可以重复的.          ---> ...