Description
[题目描述]
在直角坐标系上,有N个边平行于坐标轴的矩形。求覆盖的面积
[数据范围]
1<=N<=100
每个坐标值为[-100000000,100000000]之间的整数。
[输入文件]
第一行一个整数N
后面有N行,每行4个整数: x1 y1 x2 y2, 分别表示先后各个矩形的左下角坐标和右上角坐标。
[输出文件]
一个整数。
输入样例
3
1 1 5 3
3 2 7 4
2 5 9 7
输出样例
28
题目分析:
看到这种题目的第一种想法无非是暴力枚举,当然那也是一种我们必须要掌握的方法,很好实现也有很低的思维复杂度,在考试中往往发挥奇效
这里先对暴力的方法进行简要说明,再说明优化后的方法
这种题目如果要写暴力的话,无非是暴力到了极致,通常一点的思路是对整个坐标的图进行枚举,统计重叠的面积
这种方法很容易想到,但是我们可能会被时间复杂度给劝退,需要去寻求一种更优的方法——离散化
假设我们有如图2个矩形:
其中蓝色的是重叠部分
纳闷我们根据离散化的原理进行映射后会变成这样(PS:其中蓝色的还是重叠部分):
根据对题中给出的左下角和右上角的坐标进行重组,我们可以得到如上图中黄色线交叉的点的坐标——我们于是可以得到途中由黄色线围成的小矩形——重叠的部分也包涵在其中!
问题解决了。
但是用总结性的话来说:这题枚举离散后形成的多个小矩形就可以了
代码:
#include<bits/stdc++.h>
using namespace std;
long long a1[201],a2[201],b1[202],b2[202],x[201],y[201];
long long n,ans=0;
int main()
{
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a1[i]>>b1[i]>>a2[i]>>b2[i]; //输入坐标
x[i]=a1[i],x[i+n]=a2[i], //存储坐标,用于离散化
y[i]=b1[i],y[i+n]=b2[i];
}
//以排序的方式实现离散
sort(x+1,x+n*2+1);
sort(y+1,y+n*2+1);
for (int i = 1; i <= 2*n-1; i++) //到2n-1是因为我们需要将目前的和后面的一个配对成一个小矩形
for (int j = 1; j <= 2*n-1; j++)
for (int k = 1; k <= n; k++) //枚举所有矩形
if (x[i] >= a1[k] && y[j] >= b1[k] && x[i+1] <= a2[k] && y[j+1] <= b2[k]) //判断是否是那两个的重叠部分
{
ans += (x[i+1]-x[i]) * (y[j+1]-y[j]); //由于我们的坐标都不是在一侧的,所以可以直接这样来求出面积
break; //直接跳出循环,避免有多个矩形重叠的情况——我们只计算一次
}
cout<<ans;
return 0;
}