1. 程式人生 > >bzoj2618 [Cqoi2006]凸多邊形

bzoj2618 [Cqoi2006]凸多邊形

span lar sam per abs pac printf n) ons

[Cqoi2006]凸多邊形

Time Limit: 5 Sec Memory Limit: 128 MB

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]內的整數

我會半平面交啦啦啦~~~

半平面交我不用多說,有篇論文寫的太好啦! Orz

https://wenku.baidu.com/view/c750720bf78a6529647d53ae.html
(順面可以學一波外語~嘿嘿嘿~)

我就精心畫幾張圖來表示一下啦~~~

技術分享圖片

技術分享圖片

技術分享圖片


#include<bits/stdc++.h>
using namespace std;
struct vec{
    double x, y;
    vec() {}
    vec(double
a, double b) { x = a, y = b; } vec operator - (const vec &A){ return vec(x - A.x, y - A.y); } }; struct Line{ vec A, B; double polar; bool operator < (const Line &A)const{ return polar < A.polar; } }linL, lpl[505], lpd[505]; const int eps = 1e-8; vector<Line> L; vector<vec> ans; int
n, m, l, r; double cross(vec A, vec B){ return A.x * B.y - A.y * B.x; } bool onleft(vec A, Line X){ return cross(X.B - X.A, A - X.A) > 0; } vec inter(Line A, Line B){ double s1, s2, k; vec ret; s1 = cross((A.B - A.A), (B.B - A.A)); s2 = cross((B.A - A.A), (A.B - A.A)); k = s2 / (s1 + s2); ret.x = B.A.x + k * (B.B.x - B.A.x); ret.y = B.A.y + k * (B.B.y - B.A.y); return ret; } inline void putit() { int mx; vec p[55]; scanf("%d", &n); for(int i = 1; i <= n; ++i){ scanf("%d", &mx); for(int j = 1; j <= mx; ++j) scanf("%lf%lf", &p[j].x, &p[j].y); for(int j = 1; j < mx; ++j){ linL.A = p[j], linL.B = p[j + 1]; linL.polar = atan2(linL.B.x - linL.A.x, linL.B.y - linL.A.y); L.push_back(linL); } linL.A = p[mx], linL.B = p[1]; linL.polar = atan2(linL.B.x - linL.A.x, linL.B.y - linL.A.y); L.push_back(linL); } } inline void HPI() { sort(L.begin(), L.end()); int len = L.size() - 1; int siz = 1; lpd[1] = L[0]; for(int i = 1; i <= len; ++i){ if(L[i].polar != lpd[siz].polar) { lpd[++siz] = L[i]; continue; } if(onleft(L[i].A, lpd[siz])) lpd[siz] = L[i]; } l = 1; r = 2; lpl[1] = lpd[1], lpl[2] = lpd[2]; for(int i = 3; i <= siz; ++i){ while(l < r && !onleft(inter(lpl[r], lpl[r - 1]), lpd[i])) r--; while(l < r && !onleft(inter(lpl[l], lpl[l + 1]), lpd[i])) l++; lpl[++r] = lpd[i]; } while(l < r && !onleft(inter(lpl[r], lpl[r - 1]), lpl[l])) r--; while(l < r && !onleft(inter(lpl[l], lpl[l + 1]), lpl[r])) l++; } inline void print() { lpl[r + 1] = lpl[l]; for(int i = l; i <= r; ++i) ans.push_back(inter(lpl[i], lpl[i + 1])); if(ans.size() < 3) {printf("0.000"); return;} double ret = 0; ans.push_back(ans[0]); int len = ans.size() - 1; for(int i = 0; i < len; ++i) ret += cross(ans[i], ans[i + 1]); printf("%.3lf", fabs(ret) / 2); } int main() { putit(); HPI(); print(); return 0; }

bzoj2618 [Cqoi2006]凸多邊形