码迷,mamicode.com
首页 > 其他好文 > 详细

poj1151(扫描线)

时间:2018-06-20 22:43:43      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:stat   mit   覆盖   端点   center   sub   class   namespace   algorithm   

4837: Poj1151 Atlantis

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 21  Solved: 12
[Submit][Status][Web Board]

Description

给定平面直角坐标系中的N个矩形,求它们的面积并,即这些矩形的并集在坐标系中覆盖的总面积,如下图所示。


Input

Output

Sample Input

2
10 10 20 20
15 15 25 25.5
0

Sample Output

Test case #1
Total explored area: 180.00 

HINT

Source

求矩形围成的面积,应用扫描线

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn=1000+10;

struct line{
       int f;
       double x,y1,y2;
};

struct node{
    int l,r,c;
    double ly,ry,sum;
}tree[maxn<<2];建树

int n;
line l[maxn*2];存每条线,
double Y[maxn*4];存下所有的纵坐标,以便建树,即用从小到大后用,纵坐标进行建树,则可以匹配

bool cmp(const line &a,const line &b){
     return a.x<b.x;
}

void build(int rt,int l,int r){
     tree[rt].l=l,tree[rt].r=r;
     tree[rt].sum=0;
     tree[rt].c=0;
     tree[rt].ly=Y[l];
     tree[rt].ry=Y[r];
     if(l+1==r) return ;
     int mid=(l+r)>>1;
     build(rt<<1,l,mid);
     build(rt<<1|1,mid,r);建树操作,具体为什么是mid,我也不晓得,记得就好了
}

void calc(int rt){
     if(tree[rt].c>0) tree[rt].sum=tree[rt].ry-tree[rt].ly;如果此线被多次覆盖,那么此线长度为该点坐标之差
     else if(tree[rt].l+1==tree[rt].r) tree[rt].sum=0;若线段为点长度为0
     else tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;若不满足以上条件则线段长度从子节点中统计
}

void update(int rt,line e){
     if(e.y1==tree[rt].ly&&e.y2==tree[rt].ry){找到两个纵坐标端点重合,则找到需要计算的线段
        tree[rt].c+=e.f;
        calc(rt);
        return ;
     }
     if(e.y2<=tree[rt<<1].ry) update(rt<<1,e);若右端点在子节点的右边,即整个线段都在此端点右侧,就进子节点
     else if(e.y1>=tree[rt<<1|1].ly) update(rt<<1|1,e);同上
     else {线段被分成两份
        line t=e;
        t.y2=tree[rt<<1].ry;
        update(rt<<1,t);
        t=e;
        t.y1=tree[rt<<1|1].ly;
        update(rt<<1|1,t);
     }
     calc(rt);
}

int main(){
    int q=0;
    double ans=0;
    int t=1;
    double x1,x2,y1,y2;
    while(scanf("%d",&n)&&n){
            ans=0;
            t=1;
        for (int i=1;i<=n;i++){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            l[t].x=x1;
            l[t].y1=y1;
            l[t].y2=y2;
            l[t].f=1;
            Y[t++]=y1;
            l[t].x=x2;
            l[t].y1=y1;
            l[t].y2=y2;
            l[t].f=-1;
            Y[t++]=y2;
        }
        sort(l+1,l+t,cmp);
        sort(Y+1,Y+t);排序来建树,找线段长度
        build(1,1,t-1);只到t-1是因为t++
        update(1,l[1]);
        for (int i=2;i<t;i++){
            //printf("%lf\n",tree[1].sum);
            ans+=(l[i].x-l[i-1].x)*tree[1].sum;端点一为线段总长度
            update(1,l[i]);
        }
        printf("Test case #%d\n", ++q);
        printf("Total explored area: %.2f\n\n", ans);
    }
return 0;
}

 

poj1151(扫描线)

标签:stat   mit   覆盖   端点   center   sub   class   namespace   algorithm   

原文地址:https://www.cnblogs.com/lmjer/p/9206135.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!