链接:https://cn.vjudge.net/problem/POJ-2451
题意:半平面交求核面积。
思路:板子题,也是存板子。两个板子,思想一样,实现略微不同。
1.
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const double eps = 1e-5;
const int N = 2e4+10;
const double maxx=1e4;
int sgn(double x)
{
if(fabs(x)<eps) return 0;
else if(x<0) return -1;
else return 1;
}
struct Point
{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator -(const Point& b)const//相减
{
return Point(x-b.x,y-b.y);
}
double operator ^(const Point& b)const//叉乘
{
return x*b.y-y*b.x;
}
double operator *(const Point& b)const//点乘
{
return x*b.x+y*b.y;
}
};
struct Line
{
Point s,e;
double A;
Line(){}
Line(Point ss,Point ee)
{
s=ss,e=ee;
}
void getangle()//获得极角
{
A=atan2(e.y-s.y,e.x-s.x);
}
pair<Point,int> operator &(const Line& b)const//两直线相对关系
{
Point res=s;
if(sgn((s-e)^(b.s-b.e))==0)
{
if(sgn((b.s-s)^(b.e-s))==0)//两直线重合
return make_pair(res,0);
else return make_pair(res,1);//两直线平行
}
double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x+=(e.x-s.x)*t;
res.y+=(e.y-s.y)*t;
return make_pair(res,2);//两直线相交
}
};
Point p[N],ps[N],qu[N];
Line ls[N],q[N];
double x;
int n;
double dis(Point a,Point b)
{
return sqrt((a-b)*(a-b));
}
bool hpicmp(Line a,Line b)
{
if(sgn(a.A-b.A)!=0)
return a.A<b.A;
else return sgn((a.s-b.s)^(b.e-b.s))<0;
}
bool onright(Line l1,Line l2,Line l3)
{
Point p=(l1&l2).first;
x=((l3.e-l3.s)^(p-l3.s));
if(sgn(x)<0) return 1;
else return 0;
}
double getarea(Point p[],int n)
{
double ans=0;
for(int i=1;i<n-1;i++)
ans+=((p[i]-p[0])^(p[i+1]-p[0]));
return fabs(ans)/2.0;
}
double hpi()
{
int he=0,ta=1,cnt=0;
sort(ls,ls+n,hpicmp);
cnt=1;
for(int i=1;i<n;i++)
if(sgn(ls[i].A-ls[i-1].A)>0)
ls[cnt++]=ls[i];
q[0]=ls[0];
q[1]=ls[1];
for(int i=2;i<cnt;i++)
{
/*if(he<ta&&sgn((q[ta].e-q[ta].s)^(q[ta-1].e-q[ta-1].s))==0
||sgn((q[he].e-q[he].s)^(q[he+1].e-q[he+1].s))==0)
return 0;*/
while(he<ta&&onright(q[ta-1],q[ta],ls[i])) ta--;
while(he<ta&&onright(q[he],q[he+1],ls[i])) he++;
q[++ta]=ls[i];
}
while(he<ta&&onright(q[ta-1],q[ta],q[he])) ta--;
while(he<ta&&onright(q[he],q[he+1],q[ta-1])) he++;
if(he+1>=ta) return 0;
cnt=0;
for(int i=he;i<ta;i++)
p[cnt++]=(q[i]&q[i+1]).first;
p[cnt++]=(q[he]&q[ta]).first;
return getarea(p,cnt);
}
int main(void)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&ls[i].s.x,&ls[i].s.y);
scanf("%lf%lf",&ls[i].e.x,&ls[i].e.y);
ls[i].getangle();
}
ls[n++]=Line(Point(0,0),Point(maxx,0));
ls[n-1].getangle();
ls[n++]=Line(Point(maxx,0),Point(maxx,maxx));
ls[n-1].getangle();
ls[n++]=Line(Point(maxx,maxx),Point(0,maxx));
ls[n-1].getangle();
ls[n++]=Line(Point(0,maxx),Point(0,0));
ls[n-1].getangle();
printf("%.1f\n",hpi());
return 0;
}
2.
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const double eps = 1e-5;
const double maxx = 1e4;
const int N = 2e4+10;
int sgn(double x)
{
if(fabs(x)<eps) return 0;
else if(x<0) return -1;
else return 1;
}
struct Point
{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator -(const Point& b)const//相减
{
return Point(x-b.x,y-b.y);
}
double operator ^(const Point& b)const//叉乘
{
return x*b.y-y*b.x;
}
double operator *(const Point& b)const//点乘
{
return x*b.x+y*b.y;
}
};
struct Line
{
Point s,e;
Line(){}
Line(Point ss,Point ee)
{
s=ss,e=ee;
}
pair<Point,int> operator &(const Line& b)const//两直线相对关系
{
Point res=s;
if(sgn((s-e)^(b.s-b.e))==0)
{
if(sgn((b.s-s)^(b.e-s))==0)//两直线重合
return make_pair(res,0);
else return make_pair(res,1);//两直线平行
}
double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x+=(e.x-s.x)*t;
res.y+=(e.y-s.y)*t;
return make_pair(res,2);//两直线相交
}
};
Point ps[N];
Line ls[N],q[N];
double x;
int n;
double dis(Point a,Point b)
{
return sqrt((a-b)*(a-b));
}
double getA(Line a)
{
return atan2(a.e.y-a.s.y,a.e.x-a.s.x);
}
bool cmp(Line a,Line b)
{
double A=getA(a),B=getA(b);
if(sgn(A-B)==0)
return ((a.e-a.s)^(b.e-a.s))>=0;
else return A<B;
}
bool del(Line l1,Line l2,Line l3)
{
Point p=(l1&l2).first;
x=((l3.e-l3.s)^(p-l3.s));
if(sgn(x)<0) return 1;
else return 0;
}
double getarea(Point p[],int n)
{
double ans=0;
for(int i=1;i<n-1;i++)
ans+=((p[i]-p[0])^(p[i+1]-p[0]));
return fabs(ans)/2.0;
}
double hpi()
{
int he=0,ta=0,cnt=0;
sort(ls,ls+n,cmp);
for(int i=0;i<n-1;i++)
{
if(sgn(getA(ls[i])-getA(ls[i+1]))==0)
continue;
ls[cnt++]=ls[i];
}
ls[cnt++]=ls[n-1];
for(int i=0;i<cnt;i++)
{
while(ta-he>1&&del(q[ta-2],q[ta-1],ls[i])) ta--;
while(ta-he>1&&del(q[he],q[he+1],ls[i])) he++;
q[ta++]=ls[i];
}
while(ta-he>1&&del(q[ta-2],q[ta-1],q[he])) ta--;
while(ta-he>1&&del(q[he],q[he+1],q[ta-1])) he++;
if(ta-he<=2) return 0;
else
{
cnt=0;
for(int i=he;i+1<ta;i++)
ps[cnt++]=(q[i]&q[i+1]).first;
ps[cnt++]=(q[he]&q[ta-1]).first;
return getarea(ps,cnt);
}
}
bool judge()
{
double ans=0;
for (int i=1;i<n-1;i++)
ans+=((ps[i]-ps[0])^(ps[i+1]-ps[0]));
return ans<0;
}
int main(void)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&ls[i].s.x,&ls[i].s.y);
scanf("%lf%lf",&ls[i].e.x,&ls[i].e.y);
}
ls[n++]=Line(Point(0,0),Point(maxx,0));
ls[n++]=Line(Point(maxx,0),Point(maxx,maxx));
ls[n++]=Line(Point(maxx,maxx),Point(0,maxx));
ls[n++]=Line(Point(0,maxx),Point(0,0)); ;
printf("%.1f\n",hpi());
return 0;
}