Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 10311 | Accepted: 4056 |
Description
Input
The input file is terminated by a line containing a single 0. Don't process it.
Output
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;
}