给出一个凸多边形,和一些墙壁阻挡,求被阴影覆盖的凸多边形的长度。
对墙壁进行离散化,计算出角度(atan2)排序后进行区间合并。
然后分别计算出每个区间造成的阴影部分的长度,最后相加即可。
注意计算阴影部分于多边形的交点时,朴素的o(n)算法会导致TLE。可以用二分去优化。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <vector> using namespace std; #define mp make_pair const int MAXN = 100010; const double PI = 3.14159265358979323846264338327950288; typedef pair<double,double> pa; typedef vector<pa>::iterator iter; struct Point { double x,y; Point(double x=0,double y=0):x(x),y(y){} void input() { scanf("%lf%lf",&x,&y); } double getarg() { double r=atan2(y,x); if (r<0) r+=2*PI; return r; } double operator * (Point b) { return x*b.y-b.x*y; } Point operator - (Point b) { return Point(x-b.x,y-b.y); } }; double dis(Point a,Point b) { Point c=a-b; return sqrt(c.x*c.x+c.y*c.y); } double area(Point a,Point b,Point c) { double rul=(b-a)*(c-a); return fabs(rul); } struct Sag { Point a,b; double length; double arga,argb; void init() { length=dis(a,b); arga=a.getarg(); argb=b.getarg(); } }; vector <pa> v; Point wallp[MAXN]; Sag wall[MAXN]; int N,M; double ans; struct node { double beg; int no; node(double b,int n):beg(b),no(n){} bool operator < (node b) const { return beg<b.beg; } }; vector <node> vv; void build() { for (int i=0;i<N;i++) { if (wall[i].arga <= wall[i].argb) vv.push_back(node(wall[i].arga,i)); else { vv.push_back(node(wall[i].arga,i)); vv.push_back(node(0,i)); } } sort(vv.begin(),vv.end()); } int cros(double k) { int rul=0; rul = (upper_bound(vv.begin(),vv.end(),node(k,0))-1)->no; return rul; } double cro(Point A,Point B,Point C,Point D) { return area(A,C,D)*dis(A,B)/(area(A,C,D)+area(B,C,D)); } double calc(int p,double k) { Point C; C.x=max(wall[p].a.x,wall[p].b.x)+10; C.y=tan(k)*C.x; Point D; D.x=-C.x; D.y=-C.y; return cro(wall[p].a,wall[p].b,C,D); } void cover(double l,double r) { double rul=0; int indel=cros(l); int inder=cros(r); if (indel==inder) rul=calc(indel,r)-calc(indel,l); else { rul+=(wall[indel].length-calc(indel,l)); for (int i=(indel+1)%N;i!=inder;i=(i+1)%N) rul+=wall[i].length; rul+=calc(inder,r); } ans+=rul; } int main() { freopen("in.txt","r",stdin); scanf("%d%d",&N,&M); for (int i=0;i<N;i++) wallp[i].input(); for (int i=0;i<N;i++) wall[i].a=wallp[i]; for (int i=0;i<N-1;i++) wall[i].b=wallp[i+1]; wall[N-1].b=wallp[0]; for (int i=0;i<N;i++) wall[i].init(); for (int i=0;i<M;i++) { Point a,b; a.input(); b.input(); double ra=a.getarg(); double rb=b.getarg(); if (ra>rb) swap(ra,rb); if (rb-ra<PI) v.push_back(mp(ra,rb)); else { v.push_back(mp(0,ra)); v.push_back(mp(rb,2*PI)); } } build(); sort(v.begin(),v.end()); ans=0; double l,r; l=r=0; for (iter k=v.begin();k!=v.end();k++) { if (k->second>r) { l=max(r,k->first); r=k->second; cover(l,r); } } printf("%.12lf\n",ans); }