计算几何小结计算几何小结
计算几何小结
计算几何是个好东西,写代码感觉在写LemonLime(不你没真正写过),一层层堆叠起来,真(难)好(调)玩。
占坑
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<assert.h>
#define pf(x) ((x)*(x))
using namespace std; typedef long long ll;
inline int qr(){
int ret=0,f=0,c=getchar();
while(!isdigit(c))f|=c==45,c=getchar();
while(isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
struct NODE{
double x,y;
NODE operator + (NODE b)const{return {x+b.x,y+b.y};}
NODE operator - (NODE b)const{return {x-b.x,y-b.y};}
NODE operator * (double b)const{return {x*b,y*b};}
double operator % (NODE b)const{return x*b.y-y*b.x;}
double operator ^ (NODE b)const{return sqrt(pf(x-b.x)+pf(y-b.y));}
bool operator < (NODE b)const{return atan2(y,x)<atan2(b.y,b.x);}
bool operator == (NODE b)const{return x==b.x&&y==b.y;}
};
double atan2(NODE a){return atan2(a.y,a.x);}
struct LINE{
NODE vec,pt;
LINE(NODE a,NODE b):vec(b-a),pt(a){}
bool operator < (LINE b)const{return atan2(vec)==atan2(b.vec)?b.vec%(pt-b.pt)>0:vec<b.vec;}
NODE operator * (LINE b)const{
//no exist para
NODE A=vec,B=b.vec,C=b.pt-pt;
//if(B%A==0) return {1e9,1e9};
double t=(B%C)/(B%A);
//assert(t==t);
return pt+vec*t;
}
};
typedef vector<NODE> mat;
typedef vector<LINE> poly;
poly data;
const double bound=1000;
double sum(poly data){
if(data.size()<3) return 0;
double ret=0;
sort(data.begin(),data.end());
NODE x={0,0};
for(int t=0,ed=data.size();t<ed;++t)
ret+=(data[t]*data[(t-1+ed)%ed]-x)%(data[t]*data[(t+1)%ed]-x);
assert(ret==ret);
return ret/2;
}
poly Surface(poly _data){
sort(_data.begin(),_data.end());
poly data;
for(int t=0,r=0,ed=_data.size();r<ed;t=++r){
while(r+1<ed&&atan2(_data[t].vec)==atan2(_data[r+1].vec)) ++r;
data.push_back(_data[t]);
}
deque<LINE> q(data.begin(),data.begin()+2);
for(int t=2,ed=data.size();t<ed;++t){
while(q.size()>1){
NODE m=q[q.size()-1]*q[q.size()-2];
assert(m.x<=1e7);
if(data[t].vec%(m-data[t].pt)<0) q.pop_back();
else break;
}
while(q.size()>1){
NODE m=q[0]*q[1];
assert(m.x<=1e7);
if(data[t].vec%(m-data[t].pt)<0) q.pop_front();
else break;
}
q.push_back(data[t]);
}
while(q.size()>1){
NODE m=q[q.size()-1]*q[q.size()-2];
assert(m.x<=1e7);
if(q.front().vec%(m-q.front().pt)<0) q.pop_back();
else break;
}
while(q.size()>1){
NODE m=q[0]*q[1];
assert(m.x<=1e7);
if(q.back().vec%(m-q.back().pt)<0) q.pop_front();
else break;
}
return poly(q.begin(),q.end());
}
int main(){
int n=qr();
for(int t0=1;t0<=n;++t0){
mat sav(qr());
for(auto&t:sav) t.x=qr(),t.y=qr();
for(int i=0,ed=sav.size();i<ed;++i)
data.push_back(LINE(sav[i],sav[(i+1)%ed]));
sort(data.begin(),data.end());
}
double k=sum(Surface(data));
printf("%.5lf\n",k);
return 0;
}
博客保留所有权利,谢绝学步园、码迷等不在文首明显处显著标明转载来源的任何个人或组织进行转载!其他文明转载授权且欢迎!