题目:求多边形面积并:就是说在二维平面上给你一堆长方形,然后求所有面积的并集,重叠的地方只算一次。就相当于一张桌子上随意放了一堆多边形,求占桌子的总面积。
扫描线:
有多个黑色的矩形随机的放在一起,然后我们用这些红线从所有的矩形的竖直边将整个图分成若干长条,使得每个长条内没有矩形的竖直边。这些就是扫描线。这样操作之后,我们的面积并就好求了,只需要计算所有红线之间的小矩形面积即可。
小矩形的面积就是高乘宽,宽就是两条红线之间的距离。高就是所有在两条红线内的矩形的高的区间合并的总高度,如图:
#include<iostream>
#include<vector>
#include<algorithm>
#define x first //方便使用pair
#define y second
using namespace std;
const int N = 1010;
typedef pair<int,int> PII; //用pair来存坐标,所有坐标都是整数
typedef long long LL; //答案要用long long存
int n;
LL ans; //答案
PII l[N],r[N],q[N]; //l存左下角的坐标,r存右上角的坐标,q记两条竖线之间的区间
vector<int> xs; //xs存所有矩形的竖直边横坐标
LL range_area(int a,int b) //计算竖直线x=a和x=b之间的面积
{
LL cnt = 0,res = 0; //cnt记两条竖线内的矩形个数,res记区间合并后的高度
for(int i = 0;i < n;i++) //循环所有矩形
if(l[i].x <= a && r[i].x >= b) //判断若矩形在区间内部
q[cnt++] = {l[i].y,r[i].y}; //将该矩形竖直方向的最低点和最高点存进q
if(!cnt) //如果cnt为0,说明该两条竖线之间没有矩形
return 0; //直接返回0
sort(q,q+cnt); //区间合并,先对q进行排序
int st = q[0].x, ed = q[0].y; //st和ed是当前区间的最低点和最高点
for(int i = 1;i < cnt;i++) //循环所有区间
{
if(q[i].x <= ed) //若某区间的起点在当前区间最高点的下面
ed = max(ed,q[i].y); //更新当前区间的最高点,是这两个区间最高点的最大值
else //如果不是,说明区间断开了
{
res += ed - st; //res就加上刚刚区间的高度
st = q[i].x; //用该区间更新刚刚区间
ed = q[i].y;
}
}
res += ed - st; //res一定要加上最后一个区间的高度
return res * (b-a); //返回区间合并的高度乘宽度
}
int main()
{
cin >> n;
for(int i = 0;i < n;i++)
{
cin >> l[i].x >> l[i].y >> r[i].x >> r[i].y; //输入矩形的左下角和右上角坐标
xs.push_back(l[i].x); //把所有的竖直边的横坐标存进xs数组
xs.push_back(r[i].x);
}
sort(xs.begin(),xs.end()); //排序
for(int i = 0;i < xs.size()-1;i++) //循环每两条竖直边,计算之间的面积
if(xs[i] != xs[i+1]) //去掉重边
ans += range_area(xs[i],xs[i+1]); //答案加上这之间的面积
cout << ans << endl; //输出答案
return 0;
}