Description
在 X-Y 坐标平面上,给定多个矩形,它们的边分别与坐标轴平行。请计算它们的并的面积。
输入格式
输入第一行为一个整数 n,1<=n<=100,表示矩形的数量。
接下来有 n 行,每行包括四个数:x1,y1,x2,y2 (0<=x1<x2<=100000;0<=y1<y2<=100000),
用空格分开,不一定为整数。
(x1,y1)表示一个长方形的左下顶点坐标,(x2,y2)表示右上顶点坐标。
输出格式
n个矩形的并的面积,保留两位小数
输入样例
2
0 0 2 2
1 1 3 3
输出样例
7.00
思路1:
原来的思路是有一些错误的,即我把每两个矩形的并面积算作 S = 两个矩形面积相加 - 两个矩形相交的面积,这思路乍一看没错,我提交时也这么想,但是WA了。问题就出在了如果三个矩形都有并的面积时
三个矩形相交的面积会被多减了一次导致错误,那么四个矩形相交、五个呢,这个bug有点难改,如果有神犇有思路还望指导一下,以下是我第一次的代码(WA的)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
struct Rec{
double x1,y1;
double x2,y2;
};
Rec rec[maxn];
int main(){
int m;
double sums = 0,subs = 0;
scanf("%d",&m);
for(int i=0 ;i<m ;i++){
scanf("%lf%lf%lf%lf",&rec[i].x1, &rec[i].y1, &rec[i].x2,&rec[i].y2);
sums+= (rec[i].x2 - rec[i].x1)*(rec[i].y2 - rec[i].y1);
}
for(int i=0 ;i<m ;i++){ //去掉包含的
for(int j=0 ;j<m ;j++){
if(i == j) continue;
else if(rec[i].x1 >= rec[j].x1 && rec[i].x2 <= rec[j].x2)
if(rec[i].y1 >= rec[j].y1 && rec[i].y2 <= rec[j].y2){
sums -= (rec[i].x2 - rec[i].x1)*(rec[i].y2 - rec[i].y1);
rec[i].x1 = rec[i].x2 =rec[i].y1 =rec[i].y2 = 0;
}
}
}
//double old = 0, subss;
for(int i=0 ;i<m ;i++){ //以i为后面的和里面的矩形(被包围)
//subss = subs;
for(int j=0 ;j<m ;j++){
// old = subs;
if(i == j) continue;
if(rec[i].x1 > rec[j].x1 && rec[i].x2 > rec[j].x2 && rec[j].x2 > rec[i].x1){ //相交
if(rec[i].y2 > rec[j].y2 && rec[i].y1 > rec[j].y1 && rec[i].y1 < rec[j].y2) //右上
subs += (rec[j].x2- rec[i].x1)*(rec[j].y2 - rec[i].y1);
else if(rec[i].y2 < rec[j].y2 &&rec[i].y1 > rec[j].y1) //右中
subs += (rec[j].x2 - rec[i].x1)*(rec[i].y2 - rec[i].y1);
else if(rec[i].y2 < rec[j].y2 && rec[i].y2 > rec[j].y1 &&rec[i].y1 < rec[j].y1) //右下
subs += (rec[j].x2 - rec[i].x1)*(rec[i].y2 - rec[j].y1);
else if(rec[i].y1 < rec[j].y1 && rec[i].y2 > rec[j].y2)
subs +=(rec[j].x2 - rec[i].x1)*(rec[j].y2 - rec[j].y1); //右包含
}
else if(rec[j].x1 <= rec[i].x1 && rec[i].x2 <= rec[j].x2){ //中包含
int lenx = (rec[i].x2 - rec[i].x1);
if(rec[i].y1 > rec[j].y1 && rec[i].y2 > rec[j].y2 && rec[i].y1 <rec[j].y2) //中上
subs += lenx*(rec[j].y2 - rec[i].y1);
else if(rec[i].y1 < rec[j].y1 && rec[i].y2 < rec[j].y2 && rec[i].y2 > rec[j].y1) //下包含
subs +=(rec[i].y2 - rec[j].y1)*lenx;
else if(rec[i].y1 < rec[j].y1 && rec[i].y2 > rec[j].y2) //贯穿
subs += (rec[j].y2 - rec[j].y1)*lenx;
}
//printf("%d %d %.2lf
",i,j,subs - old);
}
//printf("*********%.2lf
",subs - subss);
}
printf("%.2lf
",sums - subs);
}
思路2:
后面这个思路是我看了大佬的代码才想出来的,主要思路是枚举在合并后矩形的各个横、纵坐标,再把横纵坐标组成的矩形面积相加,及矩阵的并面积(这里我觉得我说的不太清楚,具体看代码吧)
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
using namespace std;
struct rectangle{ //结构体,保存矩形
float x1;
float y1;
float x2;
float y2;
};
rectangle arr[101];
float x[200];
float y[200];
int flag[200][200];
int main(){
float count=0;
int n;
int k=0;
scanf("%d",&n); //数据输入
for(int i=0;i<n;i++){
scanf("%f",&arr[i].x1);
scanf("%f",&arr[i].y1);
scanf("%f",&arr[i].x2);
scanf("%f",&arr[i].y2);
x[k]=arr[i].x1; //保存所有X坐标到X[]数组,Y 到Y[]数组
y[k]=arr[i].y1;
k++;
x[k]=arr[i].x2;
y[k]=arr[i].y2;
k++;
}
sort(x,x+k); //分别排序
sort(y,y+k);for(int h=0;h<n;h++) //循环查找在矩形内的小矩形
for(int i=0;i<2*n;i++){
if(x[i]>=arr[h].x2)
break;
for(int j=0;j<2*n;j++){
if(y[j]>=arr[h].y2)
break;
if(x[i]>=arr[h].x1&&y[j]>=arr[h].y1)
flag[i][j]=1; //符合,标志
}
}
for(int i=0;i<2*n;i++) //统计面积
for(int j=0;j<2*n;j++)
count+=flag[i][j]*(x[i+1]-x[i])*(y[j+1]-y[j]);
printf("%.2f",count);
return 0;
}