POJ2451.Uyuw‘s Concert(半平面交)

POJ2451.Uyuw’s Concert(半平面交)

题意:求半平面交的核面积。

思路:板子题,需要注意的是当半平面交是一个无限平面时,要预先用4个较大线段限制住。

时间复杂度: O ( n l o g n ) O(nlogn)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-9;
#define il inline
struct P{
    double x,y;
}p[20005];
struct L{
    P p1,p2; double g;
}A[20005],q[20005];
double ANS;
int n,top,bot,tot;
il P operator-(P a,P b){
    P t; t.x=a.x-b.x; t.y=a.y-b.y;
    return t;
}
il double operator*(P a,P b){ //叉乘. 
    return a.x*b.y-b.x*a.y;
}
il bool operator<(L a,L b){
    if(a.g==b.g) return (b.p2-a.p1)*(b.p1-a.p1)>0;//越靠右,排名越靠前,会被覆盖掉
    return a.g<b.g;
}
il P inter(L a,L b){
    double k1,k2;//k1 k2 是两条线段四点连线所形成的两个三角形面积
    k1=(b.p1-a.p1)*(b.p2-a.p1),k2=(b.p2-a.p2)*(b.p1-a.p2);
    P p;
    p.x=((a.p1.x)*k2+(a.p2.x)*k1)/(k1+k2);
    p.y=((a.p1.y)*k2+(a.p2.y)*k1)/(k1+k2);
    return p;
}
il bool jud(L a,L b,L t){//判断a和b的交点是不是在t内 ,在外部返回true
    P p=inter(a,b);
    return (t.p1-p)*(t.p2-p)<0;
}
void hpi(){
    sort(A+1,A+n+1);//极角排序
    for(int i=1;i<=n;i++){//去重
        if(A[i].g!=A[i-1].g) tot++;
        A[tot]=A[i];
    }
    n=tot,q[0]=A[1],q[1]=A[2],top=1,bot=0;
    for(int i=3;i<=n;i++){
        while(bot<top&&jud(q[top],q[top-1],A[i])) top--;
        while(bot<top&&jud(q[bot],q[bot+1],A[i])) bot++;
        q[++top]=A[i];
    }
    while(bot<top&&jud(q[top],q[top-1],q[bot])) top--;
    while(bot<top&&jud(q[bot],q[bot+1],q[top])) bot++;
    q[top+1]=q[bot],tot=0;
    for(int i=bot;i<=top;i++)
        p[++tot]=inter(q[i],q[i+1]);
}
il void solve(){
    if(tot<3) return;p[++tot]=p[1];
    for(int i=1;i<=tot;i++)	//叉乘求多边形面积. 
        ANS+=p[i]*p[i+1];
    ANS=fabs(ANS)/2;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lf%lf%lf%lf",&A[i].p1.x,&A[i].p1.y,&A[i].p2.x,&A[i].p2.y);
    A[++n].p1={0,0},A[n].p2={10000,0},A[++n].p1={0,10000},A[n].p2={0,0};	//加入限制边界的四条线段. 
    A[++n].p1={10000,10000},A[n].p2={0,10000},A[++n].p1={10000,0},A[n].p2={10000,10000};
    for(int i=1;i<=n;i++)//计算每条线段的极角,即与x轴夹角,便于极角排序. 
        A[i].g=atan2((A[i].p2.y-A[i].p1.y),(A[i].p2.x-A[i].p1.x));
    hpi();solve();
    printf("%.1f",ANS);//G++要用%.f 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107575854
今日推荐