bzoj2618 [Cqoi2006]凸多邊形
阿新 • • 發佈:2018-04-15
span lar sam per abs pac printf n) ons
1 -1
2 2
-1 0
[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
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]凸多邊形