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

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define EPS 0.0000001
#define N 511
typedef double db;
const db PI=acos(-1.0);
struct Point{db x,y;};
typedef Point Vector;
Vector operator - (const Point &a,const Point &b){return (Vector){a.x-b.x,a.y-b.y};}
Vector operator * (const Vector &a,const db &k){return (Vector){a.x*k,a.y*k};}
Vector operator + (const Vector &a,const Vector &b){return (Vector){a.x+b.x,a.y+b.y};}
db Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Line
{
    Point p; Vector v; db ang;
    Line(){}
    Line(const Point &a,const Point &b)
      {
        v=b-a;
        p=a;
        ang=atan2(v.y,v.x);
        if(ang<0) ang+=2.0*PI;
      }
};
bool operator < (const Line &a,const Line &b){return a.ang<b.ang;}
bool OnLeft(Line l,Point a){return Cross(l.v,a-l.p)>0;}
Point GetJiaodian(Line a,Line b){return a.p+a.v*(Cross(b.v,a.p-b.p)/Cross(a.v,b.v));}
int n;
Point ps[N];
Line q[N];
int head=1,tail=1;
Line ls[N];
void BPMJ()
{
    sort(ls+1,ls+n+1);
    q[1]=ls[1];
    for(int i=2;i<=n;++i)
      {
        while(head<tail&&(!OnLeft(ls[i],ps[tail-1]))) --tail;
        while(head<tail&&(!OnLeft(ls[i],ps[head]))) ++head;
        q[++tail]=ls[i];
        if(fabs(Cross(q[tail].v,q[tail-1].v))<EPS)
          {
            --tail;
            if(OnLeft(q[tail],ls[i].p))
              q[tail]=ls[i];
          }
        if(head<tail)
          ps[tail-1]=GetJiaodian(q[tail-1],q[tail]);
      }
    while(head<tail&&(!OnLeft(q[head],ps[tail-1]))) --tail;
    ps[tail]=GetJiaodian(q[tail],q[head]);
}
int nn,mm;
Point tmp[51];
db area;
int main()
{
    scanf("%d",&nn);
    for(int i=1;i<=nn;++i)
      {
        scanf("%d",&mm);
        for(int j=1;j<=mm;++j) scanf("%lf%lf",&tmp[j].x,&tmp[j].y);
        for(int j=1;j<mm;++j) ls[++n]=Line(tmp[j],tmp[j+1]);
        ls[++n]=Line(tmp[mm],tmp[1]);
      }
    BPMJ();
    for(int i=head+1;i<tail;++i)
      area+=Cross(ps[i]-ps[head],ps[i+1]-ps[head]);
    printf("%.3lf\n",area/2.0);
    return 0;
}
时间: 2024-12-28 08:13:24

【半平面交】bzoj2618 [Cqoi2006]凸多边形的相关文章

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

这是一道半平面交的裸题,第一次写半平面交,就说一说我对半平面交的理解吧. 所谓半平面交,就是求一大堆二元一次不等式的交集,而每个二元一次不等式的解集都可以看成是在一条直线的上方或下方,联系直线的标准方程就可以得出.于是乎这些不等式就可以转化为一些半平面,求的就是半平面交. 而半平面交不可能交出凹多边形(因为凹多边形的定义是有一条边所在的直线能把该多边形分成若干块...YY一下就知道这是不可能的),这是一个十分优美的性质,正类似于凸包(写法也是有些相似的),但半平面交可能交出无界,于是可以加四条类

BZOJ-2618 [CQOI2006]凸多边形

半平面交模版题.. #include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #include <cctype> #include <algorithm> #define rep(i, l, r) for(int i=l; i<=r; i++) #define clr(x, c) memset(x, c, sizeof(x)) #define

BZOJ2618 [Cqoi2006]凸多边形

那个叫啥,半平面交... 第一次写于是只能按照惯例,orz hzwer去~~~ 把一个凸多边形搞成好多条线段,于是题目就变成了一堆线段的半平面交... 怎么感觉比仙人掌还简单一点的说...就是有点长 1 /************************************************************** 2 Problem: 2618 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:0 ms 7 Memo

Rotating Scoreboard(半平面交模板题)

Rotating Scoreboard http://poj.org/problem?id=3335 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8506   Accepted: 3357 Description This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spe

【BZOJ2618】【Cqoi2006】凸多边形 半平面交 、算法的深度细节剖析。

题解:虽然这道题数据范围太小,O(n*n)的算法都能过,但是我为了练手仍写了半平面交.. 半平面交: 我们规定:一个基准点+一个向量(本质是有向直线,)就算一个半平面,现在要求出半平面交,然后做一些事情.. 那么可以过每个半平面的基准点做一条平行于x轴的向右的射线,此射线与向量代表直线的夹角为其"极角".. 我们可以把所有半平面(Line,或者说叫有向直线)以其极角为键值排序, 然后扫一圈,围出来一个图形,即要求的半平面交.. 实现过程不妨看代码,有详细注释. 代码中有几个需要画图的地

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

2618: [Cqoi2006]凸多边形 Description 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. Input 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形.第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标. Output 输出文件仅包含一个实数,表示相交部分的面积,保留三位小数. Sample Input 2 6 -2 0 -1 -2 1

poj 3384 Feng Shui 半平面交的应用 求最多覆盖凸多边形的面积的两个圆 的圆心坐标

题目来源: http://poj.org/problem?id=3384 分析: 用半平面交将多边形的每条边一起向"内"推进R,得到新的多边形(半平面交),然后求多边形的最远两点. 代码如下: const double EPS = 1e-10; const int Max_N = 105 ; struct Point{ double x,y; Point(){} Point(double x, double y):x(x),y(y){} Point operator - (Point

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

题目描述 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. 输入 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形.第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标. 输出 输出文件仅包含一个实数,表示相交部分的面积,保留三位小数. 样例输入 2 6 -2 0 -1 -2 1 -2 2 0 1 2 -1 2 4 0 -3 1 -1 2 2 -1 0 样例输出

poj 3525 Most Distant Point from the Sea 半平面交 + 二分

题目来源: http://poj.org/problem?id=3525 分析: 题意:给定一个凸多边形,求多边形中距离边界最远的点到边界的距离. 思路 : 每次将凸多边形每条边往里平移d,判断是否存在核:二分d即可. 多边形边上的点(x , y)往里平移d 后的 坐标: s , e  为向量的 起点和终点, len 为起点和终点的距离, h 为平移的距离 x' = x + dx y' = y + dy dx = ( s.y - e.y ) / len * h ,( 原理 是 利用 三角形的相似