• 【转】POJ 1151 Atlantis


    Atlantis
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 10311   Accepted: 4056

    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 Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

    Input

    The input consists of several test cases. Each test case starts with a line containing a single integer n (1 <= n <= 100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area. 
    The input file is terminated by a line containing a single 0. Don't process it.

    Output

    For each test case, your program should output one section. The first line of each section must be "Test case #k", where k is the number of the test case (starting with 1). The second one must be "Total explored area: a", where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point. 
    Output a blank line after each test case.

    Sample Input

    2 10 10 20 20 15 15 25 25.5 0

    Sample Output

    Test case #1 Total explored area: 180.00

    Source

     

     

     

     

    //

    * poj Atlantis

    * 解题思路:

    * (引用)

    题意:地图上有一些矩形区域,但其中有某些区域有部分重叠。现给定各矩形的坐标,求所有矩形覆盖的总面积。

    思路:题目求平面上矩形的覆盖面积。其中一种方法是通过线段树去求。矩形坐标范围是0-10^5,而且是小数,但数目却只有100个。因此需要先对坐标进行离散化,再去通过线段树进行计算。线段树算面积交的步骤是,按一个方向扫描整个区域,例如,从左向右。对于矩形的左垂直边,进行插入线段操作;对于矩形的右垂直边,进行删除线段操作。而上下水平边的作用,仅仅是用来记录垂直边的端点位置。对于每条垂直边,在操作之后,需要计算当前区间的面积,即从一条垂直边到下一条垂直边之间的覆盖面积。方法就是矩形面积计算公式,一条边为当前线段长度,另一条边为两垂直边的距离。

     

    * 线段树

     

    #include <iostream>

    #include <string>

    #include <cstring>

    #include <cstdio>

    #include <cstdlib>

    #include <map>

    #include <set>

    #include <vector>

    #include <queue>

    #include <functional>

    #include <algorithm>

    #include <cmath>

    #include <assert.h>

    #include <stack>

    using namespace std;

     

    #define le 102

     

    typedef struct {

        int b , e , c;

        double len , lt , rt;

    }re;

    re seg[6*le];

     

    typedef struct {

        double y1 , y2 , x;

        int flag;

    }ore;

    ore line[le << 1];

     

    double tb[ le << 1 ];

     

    int n , k , p;

     

    bool cmp ( ore va , ore vb ){

        return va.x < vb.x;

    }

     

    void descretize (){

        int i , t = 1;

        sort ( tb + 1 , tb + k );

        for ( i = 1 ; i < k ; i++ ){

            if ( tb[i] != tb[t] )

                tb[++t] = tb[i];

        }

        k = t;

    }

     

    void input (){

        int i;

        double x1 , y1 , x2 , y2;

        k = 1;

        for ( i = 1 ; i <= n ; i++ ){

            scanf ( "%lf%lf%lf%lf" , &x1 , &y1 , &x2 , &y2 );

            line[k].x = x1;

            line[k].y1 = y1; line[k].y2 = y2;

            line[k].flag = 1;

            tb[k] = y1;

            k++;

            line[k].x = x2;

            line[k].y1 = y1; line[k].y2 = y2;

            line[k].flag = -1;

            tb[k] = y2;

            k++;

        }

        p = k - 1;

        sort ( line + 1 , line + k , cmp );

        descretize();

    }

     

    void make_tree ( int lt , int rt , int v ){

        int mid;

        seg[v].b = lt; seg[v].e = rt;

        seg[v].c = 0;

        seg[v].len = 0;

        seg[v].lt = tb[lt];

        seg[v].rt = tb[rt];

        if ( lt + 1 < rt ){

            mid = ( lt + rt ) >> 1;

            make_tree ( lt , mid , v << 1 );

            make_tree ( mid , rt , v << 1 | 1 );

        }

    }

     

    void cal_len ( int v ){

        if ( seg[v].c > 0 ){

            seg[v].len = seg[v].rt - seg[v].lt;

            return ;

        }

        if ( seg[v].b + 1 == seg[v].e ) seg[v].len = 0;

        else seg[v].len = seg[v << 1].len + seg[v << 1 | 1].len;

    }

     

    void update ( int v , ore tip ){

        int lc , rc;

        if ( tip.y1 == seg[v].lt && seg[v].rt == tip.y2 ){

            seg[v].c += tip.flag;

            cal_len ( v );

            return ;

        }

        lc = v << 1;

        rc = lc | 1;

        if ( tip.y2 <= seg[lc].rt ) update ( lc , tip );

        else if ( tip.y1 >= seg[rc].lt ) update ( rc , tip );

        else {

            ore tem = tip;

            tem.y2 = seg[lc].rt;

            update ( lc , tem );

            tem = tip;

            tem.y1 = seg[rc].lt;

            update ( rc , tem );

        }

        cal_len ( v );

    }

     

    void deal (){

        int i;

        double area(0);

        make_tree ( 1 , k , 1 );

        update ( 1 , line[1] );

        for ( i = 2 ; i <= p ; i++ ){

            area += seg[1].len * ( line[i].x - line[i - 1].x );

            update ( 1 , line[i] );

        }

        printf ( "Total explored area: %.2lf\n" , area );

        putchar ('\n');

    }

     

    int main (void){

        int cas(0);

        while ( scanf ( "%d" , &n ) == 1 && n){

            input ();

            printf ( "Test case #%d\n" , ++cas );

            deal ();

        }

        return 0;

    }

  • 相关阅读:
    使用Fiddler抓取手机APP数据包--360WIFI
    mysql 查询数据库表信息,字段信息
    jQuery动态移除和绑定事件
    Topshelf+Quatz.Net的简单使用
    教你花30分钟时间搭建一个个人博客
    泛型接口的抗变和协变
    Action<T>和Func<T>
    DateTime和DateTimeOffset的区别
    Expression<Func<TObject, bool>>与Func<TObject, bool>的区别
    C#学习笔记(1) --简叙.net体系结构
  • 原文地址:https://www.cnblogs.com/lzhitian/p/2587897.html
Copyright © 2020-2023  润新知