描述
在 X-Y 坐标平面上,给定多个矩形,它们的边分别与坐标轴平行。请计算它们的并的面积。
输入格式
输入第一行为一个整数 n,1<=n<=100,表示矩形的数量。
接下来有 n 行,每行包括四个数:x1,y1,x2,y2 (0<=x1
(x1,y1)表示一个长方形的左下顶点坐标,(x2,y2)表示右上顶点坐标。
输出格式
n个矩形的并的面积,保留两位小数。
输入样例
2
0 0 2 2
1 1 3 3
输出样例
7.00
Hint
此题没能用上递归、分治或其他等一系列方法。以下为推荐思路,鼓励自行思考别的方法。
第一题本为练笔,但我挑选的此题似乎实现起来麻烦。
对不住大家了!若实在觉得繁琐的可跳过此题。:(
但,练练手总没坏处滴 :)
多个矩形面积重叠没有规律,难以直接求解或用上递归的思路。
只能从矩形重叠的情况入手,进行局部相加。
1)将所有矩形的左右边界都投影到X轴上,形成各个区间
2)从左向右计算每个区间,将落在该区间内的矩形进行面积统计
3)将每个区间计算的面积再相加
1.[代码][C/C++]代码
#include
#include
using namespace std;
typedef struct LevelSeg //用来记录一个水平线段的结构体
{
double l, r; //l是水平线段的的左顶点x坐标,r是水平线段的右顶点x坐标
double y; //y是一个水平线段的y坐标
int UpOrDown; //标记这个水平线段是上边还是下边, 0 是下边,1 是上边
}LevelSeg;
// 对LevelSeg按照Y坐标的值进行从大到小的排序
int Partition(LevelSeg L[], int low, int high) {
L[0] = L[low];
double pivotkey = L[low].y;
while(low < high) {
while(low < high && L[high].y <= pivotkey) --high;
L[low] = L[high];
while(low < high && L[low].y >= pivotkey) ++low;
L[high] = L[low];
}
L[low] = L[0];
return low;
}
void qsort(LevelSeg L[], int low, int high) {
if(low < high) {
double pivotloc = Partition(L, low, high);
qsort(L, low, pivotloc - 1);
qsort(L, pivotloc + 1, high);
}
}
int main() {
int n = 0;
double x1, x2, y1, y2;
LevelSeg ls[201];
set X; // 记录所有x坐标
double area = 0;
scanf("%d", &n);
// 初始化所有矩形
if(n >= 1 && n <=100) {
for(int i = 1; i <= 2*n; i += 2) {
scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
ls[i].l = x1;
ls[i].r = x2;
ls[i].y = y1;
ls[i].UpOrDown = 0; // 下边
ls[i+1].l = x1;
ls[i+1].r = x2;
ls[i+1].y = y2;
ls[i+1].UpOrDown = 1; // 上边
X.insert (x1);
X.insert (x2);
}
}
// 对LevelSeg进行排序
qsort(ls,1,2*n);
set::iterator di;
di = X.begin();
for(int j = 1; j< X.size(); j ++){
int mark = 0;
double maxY = 0;
int count = 0; // 计数器
x1 = *(di);
x2 = *(++di);
//std::cout << *di << " ";
for(int i = 1; i <= 2*n; i ++){
if(x1 >= ls[i].l && x2 <= ls[i].r){
if(0 == mark) {
maxY = ls[i].y;
mark = 1;
}
if(ls[i].UpOrDown) {
count ++;
}else {
count --;
}
if(0 == count){
area += (x2 - x1)*(maxY - ls[i].y);
mark = 0;
}
}
}
}
printf("%.2lf", area);
return 0;
}