【 [CQOI2006]凸多边形】暴力半平面交
半平面交总觉得和线性规划莫名的像?
https://www.luogu.org/problemnew/show/P4196
题目描述
逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233。输入输出格式
输入格式: 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。 输出格式: 输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。输入输出样例
说明
100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数 直接暴力求半平面交O(n^2)裸题。之后再考虑写O(n)半平面交吧。#include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cmath> #include<cassert> using namespace std; typedef double db; const int maxn = 505; const db eps = 1e-8; struct pt{ db x,y; }s[maxn],r[maxn],t[maxn]; int tot; pt operator+(pt a,pt b) { return (pt){a.x+b.x,a.y+b.y}; } pt operator-(pt a,pt b) { return (pt){a.x-b.x,a.y-b.y}; } pt operator*(db k,pt a) { return (pt){k*a.x,k*a.y}; } db operator*(pt a,pt b) { return a.x*b.x+a.y*b.y; } db operator^(pt a,pt b) { return a.x*b.y-a.y*b.x; } struct line{ pt p,v; }; pt getcut(line a,line b) { //assert(fabs(aa.v^bb.v)<eps); db k = ( (b.p-a.p)^a.v )/(a.v^b.v); return b.p + k*b.v; } void CUT(line a) { int i,j,k,o=0; s[tot+1]=s[1]; s[0] = s[tot]; for(int i=1;i<=tot;i++) { if(((a.v)^(s[i]-a.p))<eps) { if( ((a.v)^(s[i-1]-a.p))>eps) { t[++o] = getcut((line){s[i-1],s[i]-s[i-1]},a); } if( ((a.v)^(s[i+1]-a.p)) > eps) { t[++o] = getcut((line){s[i],s[i+1]-s[i]},a); } } else t[++o] = s[i]; } for(int i=1;i<=o;i++) s[i] = t[i]; tot = o; } int n; int main() { scanf("%d",&n); s[1] = (pt){-1e5,-1e5}; s[2] = (pt){1e5,-1e5}; s[3] = (pt){1e5,1e5}; s[4] = (pt){-1e5,1e5}; tot = 4; for(int tim = 1;tim <= n; tim++) { int k; scanf("%d",&k); for(int i=1;i<=k;i++) { scanf("%lf%lf",&r[i].x,&r[i].y); } r[k+1] = r[1]; for(int i=1;i<=k;i++) { CUT( (line){r[i],r[i+1]-r[i]} ); } } db ans = 0; s[tot+1] = s[1]; for(int i=1;i<=tot;i++) { ans += (s[i]^s[i+1]); } printf("%.3lf\n",ans/2); }