题意
在一个有限大(-10 0000<=x,y<=10 0000)的平面坐标系上有n个半平面(注意有限的),每个半平面给出一条有向线段(x1,y1)——>(x2,y2)。
每个半平面的有效区域都是左侧。求这n个半平面的交的面积。
题解
半平面交的模板
以前偷懒,学了个
(n2)
(
n
2
)
的,但是已经忘了啊
于是今天趁没网学了个
的nlogn
的
n
l
o
g
n
模板调了一个多小时QAQ
现在才会啊
感觉也不难。。
就这样,存下板子吧。。
教程我就不写了
CODE:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const double MAX=100001;
const int N=20005;
const double eps=1e-8;
int n;
struct pnt{double x,y;};
struct qq
{
pnt x,y;
double angle;
}s[N];int tot=0;
void add (double x1,double y1,double x2,double y2)
{
tot++;
s[tot].x.x=x1;
s[tot].x.y=y1;
s[tot].y.x=x2;
s[tot].y.y=y2;
/*s[tot].x=pnt{x1,y1};
s[tot].y=pnt{x2,y2};*/
s[tot].angle=atan2(y2-y1,x2-x1);
}
double mul (pnt x,pnt y,pnt z)
{
double x1=x.x-z.x,x2=y.x-z.x;
double y1=x.y-z.y,y2=y.y-z.y;
return x1*y2-x2*y1;
}
bool cmp (qq x,qq y)
{
if (abs(x.angle-y.angle)<eps)
return mul(x.y,y.y,x.x)<-eps;
return x.angle<y.angle;
}
int q[N];
pnt JD(qq x,qq y)//两条直线的交点
{
double s1=mul(x.y,y.x,x.x);
double s2=mul(x.y,x.x,y.y);
pnt xx;
xx.x=(y.x.x*s2+y.y.x*s1)/(s1+s2);
xx.y=(y.x.y*s2+y.y.y*s1)/(s1+s2);
return xx;
}
bool check (qq x,qq a,qq b)//a,b的交点是不是在x的右侧
{
pnt xx=JD(a,b);
return mul(x.y,xx,x.x)<-eps;
}
pnt ans[N];
void solve ()
{
sort(s+1,s+1+tot,cmp);
n=1;
for (int u=2;u<=tot;u++)
if (abs(s[u].angle-s[n].angle)>eps)
s[++n]=s[u];
int st=1,ed=2;
q[1]=1;q[2]=2;
for (int u=3;u<=n;u++)
{
while (st<ed&&check(s[u],s[q[ed]],s[q[ed-1]])) ed--;
while (st<ed&&check(s[u],s[q[st]],s[q[st+1]])) st++;
q[++ed]=u;
}
while (st<ed&&check(s[q[st]],s[q[ed]],s[q[ed-1]])) ed--;
while (st<ed&&check(s[q[ed]],s[q[st]],s[q[st+1]])) st++;
q[++ed]=q[st];
n=0;
for (int u=st;u<ed;u++)
ans[++n]=JD(s[q[u]],s[q[u+1]]);
/*for (int u=1;u<=n;u++)
printf("YES:%lf %lf\n",ans[u].x,ans[u].y);*/
}
int main()
{
scanf("%d",&n);
for (int u=1;u<=n;u++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
add(x1,y1,x2,y2);
}
add(-MAX,-MAX,MAX,-MAX);
add(MAX,-MAX,MAX,MAX);
add(MAX,MAX,-MAX,MAX);
add(-MAX,MAX,-MAX,-MAX);
solve();
if (n<=2)
{
printf("0.0\n");
return 0;
}
double lalal=0;
for (int u=3;u<=n;u++)
lalal=lalal+mul(ans[u],ans[u-1],ans[1]);
printf("%.1lf\n",abs(lalal)/2);
return 0;
}