矩阵的并
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 \n",i,j,subs - old); } //printf("*********%.2lf\n",subs - subss); } printf("%.2lf\n",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; }