半平面交
Posted yinwuxiao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了半平面交相关的知识,希望对你有一定的参考价值。
题解:
把n凸边型转化为n条边后
等价于给出k条直线,让你求直线左边区域的交
然后大概步骤是
首先要给边排序,按照极角从-pai开始逆时针排序
另外平行边我们只需要保留那条约束条件更强的
维护一个双端队列
加点之后判断$(p[h],p[h+1])$的交点$(p[t-1],p[t])$的交点是否在当前直线右边
如果是就不断循环暴力弹
做完之后由于把最后的平面都直接加进来了,所以还要删除没用的
就是$(p[t],p[t-1])$在$p[h]$右边的
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (int i=h;i<=t;i++) #define dep(i,t,h) for (int i=t;i>=h;i--) const int N=2e5; const double eps=1e-6; struct point { double a,b; point operator +(point o) { return (point){a+o.a,b+o.b}; } point operator -(point o) { return (point){a-o.a,b-o.b}; } point operator *(double x) { return (point){x*a,x*b}; } point operator /(double x) { return (point){a/x,b/x}; } double operator *(point x) { return x.a*a+x.b*b; } double operator ^(point x) { return a*x.b-x.a*b; } }p[N],a[N]; struct line { point a,b; }s[N],l[N]; int tt,st,m; IL bool pd(line x,line y) { double tt=x.b^y.b; return (tt>0||(tt==0&&(x.b^(y.a-x.a))>0)); } bool cmp(line x,line y) { if (x.b.b==0&&y.b.b==0) return x.b.a<y.b.a; if ((x.b.b<=0&&y.b.b<=0)||(x.b.b>0&&y.b.b>0)) return pd(x,y); return x.b.b<y.b.b; } bool pd2(line x,line y) { return x.b^y.b; } bool pd3(point x,line y) { return (y.b^(x-y.a))<=0; } point get_j(line x,line y) { double k=(y.a-x.a)^y.b/(x.b^y.b); return x.a+(x.b*k); } IL double area(point a,point b,point c) { return (abs)((b-a)^(c-a)); } void solve() { sort(l+1,l+m+1,cmp); int tp=0; rep(i,1,m) { if(i==1||pd2(l[i],l[i-1])) tp++; l[tp]=l[i]; } m=tp; int h=1,t=2; s[1]=l[1],s[2]=l[2]; rep(i,3,m) { while (h<t&&pd3(get_j(s[t],s[t-1]),l[i])) t--; while (h<t&&pd3(get_j(s[h],s[h+1]),l[i])) h++; s[++t]=l[i]; } while (h<t&&pd3(get_j(s[t],s[t-1]),s[h])) t--; if (t-h<=1) {printf("0.000"); return;} tp=0; s[h-1]=s[t]; rep(i,h,t) a[++tp]=get_j(s[i],s[i-1]); double ans=0; rep(i,3,tp) ans+=area(a[1],a[i-1],a[i])/2; printf("%.3lf",ans); } int main() { ios::sync_with_stdio(false); int tt; cin>>tt; int n=0; while (tt--) { int k; cin>>k; int st=n+1; while (k--) { double x,y; cin>>x>>y; p[++n]=(point){x,y}; if (n>st) l[++m]=(line){p[n-1],p[n]-p[n-1]}; } l[++m]=(line){p[n],p[st]-p[n]}; } solve(); return 0; }
以上是关于半平面交的主要内容,如果未能解决你的问题,请参考以下文章