poj1151(扫描线)

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;
}

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

时间: 2024-11-02 04:55:34

poj1151(扫描线)的相关文章

线段树+扫描线+离散化解poj1151 hdu 1542 ( Atlantis )

受此链接很大启发才明白扫描线: http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html 我的代码如下: #include<iostream> #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #i

POJ1151 Atlantis 【扫描线】+【线段树】+【离散化】

Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16882   Accepted: 6435 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of

【POJ1151】Atlantis(线段树,扫描线)

[POJ1151]Atlantis(线段树,扫描线) 题面 Vjudge 题解 学一学扫描线 其实很简单啦 这道题目要求的就是若干矩形的面积和 把扫描线平行于某个轴扫过去(我选的平行\(y\)轴扫) 这样只需要求出每次和\(x\)轴覆盖的长度 就可以两两相乘,求出面积 最后累计和就行啦 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cma

POJ1151 Atlantis 【扫描线】

Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16882   Accepted: 6435 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of

【POJ1151】【扫描线+线段树】Atlantis

Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend

ACM学习历程—POJ1151 Atlantis(扫描线 &amp;&amp; 线段树)

Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend

poj1151 Atlantis——扫描线+线段树

题目:http://poj.org/problem?id=1151 经典的扫描线问题: 可以用线段树的每个点代表横向被矩形上下边分割开的每一格,这样将一个矩形的出现或消失化为线段树上的单点修改: 每个格子记录两个值:c(矩形存在情况),sum(对当前答案作出贡献的长度): 将y离散化作为建树的依据: 一开始没想到线段树上的点应该是横向的格子,写了个乱七八糟: #include<iostream> #include<cstdio> #include<cstring> #i

poj3277--City Horizon(线段树+离散化+扫描线)

City Horizon Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16206   Accepted: 4414 Description Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the city horizon and observe the beautiful silhouette

poj1151

Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21511   Accepted: 8110 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of