zoukankan      html  css  js  c++  java
  • 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
    ",tree[1].sum);
                ans+=(l[i].x-l[i-1].x)*tree[1].sum;端点一为线段总长度
                update(1,l[i]);
            }
            printf("Test case #%d
    ", ++q);
            printf("Total explored area: %.2f
    
    ", ans);
        }
    return 0;
    }
  • 相关阅读:
    【HDOJ】4370 0 or 1
    【HDOJ】4122 Alice's mooncake shop
    【HDOJ】4393 Throw nails
    【HDOJ】2385 Stock
    WinCE 输入法编程
    WinCE 自由拼音输入法的测试
    SQL Server CE开发环境建立过程
    【SQL Server CE2.0】创建加密的数据库(源代码)
    【SQL Server CE2.0】打开加密的数据库(源代码)
    EVC在双核PC上调试速度慢的原因
  • 原文地址:https://www.cnblogs.com/lmjer/p/9206135.html
Copyright © 2011-2022 走看看