BZOJ2618 [Cqoi2006]凸多边形

那个叫啥,半平面交。。。

第一次写于是只能按照惯例,orz hzwer去~~~

把一个凸多边形搞成好多条线段,于是题目就变成了一堆线段的半平面交。。。

怎么感觉比仙人掌还简单一点的说。。。就是有点长

  1 /**************************************************************
  2     Problem: 2618
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:0 ms
  7     Memory:932 kb
  8 ****************************************************************/
  9
 10 #include <cstdio>
 11 #include <cmath>
 12 #include <algorithm>
 13
 14 using namespace std;
 15 typedef double lf;
 16 const int N = 1005;
 17 struct Point{
 18     lf x, y;
 19     Point(void){}
 20     Point(lf a, lf b) : x(a), y(b){}
 21 }p[N], a[N];
 22
 23 struct Line{
 24     Point a, b;
 25     lf slope;
 26     Line(void){}
 27     Line(Point x, Point y, lf z) : a(x), b(y), slope(z){}
 28 }l[N], q[N];
 29 int n, cnt, tot, num;
 30 lf ans;
 31
 32 inline int read(){
 33     int x = 0, sgn = 1;
 34     char ch = getchar();
 35     while (ch < ‘0‘ || ch > ‘9‘){
 36         if (ch == ‘-‘) sgn = -1;
 37         ch = getchar();
 38     }
 39     while (ch >= ‘0‘ && ch <= ‘9‘){
 40         x = x * 10 + ch - ‘0‘;
 41         ch = getchar();
 42     }
 43     return sgn * x;
 44 }
 45
 46 inline lf operator * (const Point a, const Point b){
 47     return a.x * b.y - a.y * b.x;
 48 }
 49
 50 inline Point operator - (const Point a, const Point b){
 51     return Point(a.x - b.x, a.y - b.y);
 52 }
 53
 54 inline bool operator < (const Line a, const Line b){
 55     return a.slope == b.slope ? (a.b - a.a) * (b.b - a.a) > 0 : a.slope < b.slope;
 56 }
 57
 58 inline Point inter(const Line a, const Line b){
 59     lf k1, k2, tmp;
 60     Point res;
 61     k1 = (b.b - a.a) * (a.b - a.a);
 62     k2 = (a.b - a.a) * (b.a - a.a);
 63     tmp = k1 / (k1 + k2);
 64     res = Point(b.b.x + tmp *(b.a.x - b.b.x), b.b.y + tmp * (b.a.y - b.b.y));
 65     return res;
 66 }
 67
 68 inline bool check(const Line a, const Line b, const Line t){
 69     Point p = inter(a, b);
 70     return (t.b - t.a) * (p - t.a) < 0;
 71 }
 72
 73 void work(){
 74     sort(l + 1, l + cnt + 1);
 75     int L = 1, R = 2;
 76     tot = 0;
 77     for (int i = 1; i <= cnt; ++i){
 78         if (l[i].slope != l[i -1].slope) ++tot;
 79         l[tot] = l[i];
 80     }
 81
 82     cnt = tot, tot = 0;
 83     q[1] = l[1], q[2] = l[2];
 84     for (int i = 3; i <= cnt; ++i){
 85         while (L < R && check(q[R - 1], q[R], l[i])) --R;
 86         while (L < R && check(q[L + 1], q[L], l[i])) ++L;
 87         q[++R] = l[i];
 88     }
 89     while (L < R && check(q[R - 1], q[R], q[L])) --R;
 90     while (L < R && check(q[L + 1], q[L], q[R])) ++L;
 91     q[R + 1] = q[L];
 92     for (int i = L; i <= R; ++i)
 93         a[++tot] = inter(q[i], q[i + 1]);
 94 }
 95
 96 void get_ans(){
 97     ans = 0;
 98     if (tot < 3) return;
 99     a[++tot] = a[1];
100     for (int i = 1; i <= tot; ++i)
101         ans += a[i] * a[i + 1];
102     ans = fabs(ans) / 2;
103 }
104
105 int main(){
106     n = read();
107     int X, Y;
108     for (int i = 1; i <= n; ++i){
109         num = read();
110         for (int j = 1; j <= num; ++j){
111             X = read(), Y = read();
112             p[j] = Point(X, Y);
113         }
114         p[num + 1] = p[1];
115         for (int j = 1; j <= num; ++j)
116             l[++cnt] = Line(p[j], p[j + 1], 0);
117     }
118     for (int i = 1; i <= cnt; ++i)
119         l[i].slope = atan2(l[i].b.y - l[i].a.y, l[i].b.x - l[i].a.x);
120     work();
121     get_ans();
122     printf("%.3lf\n", ans);
123     return 0;
124 }

时间: 2024-11-05 19:00:24

BZOJ2618 [Cqoi2006]凸多边形的相关文章

【半平面交】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,c

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

【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

【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 样例输出

BZOJ 2618 CQOI2006 凸多边形 半平面交

题目大意:给定n个凸多边形,求交集的面积 时隔多年我终于把完整的半平面交搞出来了--真尼玛艰辛-- 曾经写了一发 RE到死 于是就搁置0.0 今天写一发又是WA到死的节奏-- 不多说直接上代码 其实刘汝佳同学写麻烦了 每次插入一个半平面之后不用两端都删的 只删一端 最后再处理两端的部分就行 300题留念--切了道模板题也不错 #include <cmath> #include <cstdio> #include <cstring> #include <iostre

●BZOJ 2618 [Cqoi2006]凸多边形

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2618 题解: 计算几何,半平面交. 给出一些凸包,求面积交. 把所有边都取出来,直接办平面交就好.    原来dcmp也不能滥用,之前把所有的大于小于比较都用了dcmp函数,导致错误. (以后除了double型判等,其它时候尽量不用dcmp好了) 代码: #include<cmath> #include<cstdio> #include<cstring> #inc

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

嘟嘟嘟 本来我要写feng shui这道题的.然后网上都说什么半平面相交,于是我还得现学这个东西,就来刷这道模板题了. 所谓的半平面相交和高中数学的分数规划特别像.比如这道题,把每一条边看成一条有向直线,则合法的范围都是直线的右半部分,最后求交集.大概是每一次都取一半,所以就叫半平面相交吧. \(O(n ^ 2)\)的做法很简单,我也只会\(O(n ^ 2)\)的.枚举每一条边,然后用这条边去切当前算出来的图形. 具体怎么切?一句话就是把这条直线左边的点全部扔掉. 放个伪代码就明白了: for

【模板】半平面交

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