扫描线模板

题目:

求多边形面积并:就是说在二维平面上给你一堆长方形,然后求所有面积的并集,重叠的地方只算一次。就相当于一张桌子上随意放了一堆多边形,求占桌子的总面积。

扫描线:

有多个黑色的矩形随机的放在一起,然后我们用这些红线从所有的矩形的竖直边将整个图分成若干长条,使得每个长条内没有矩形的竖直边。这些就是扫描线。这样操作之后,我们的面积并就好求了,只需要计算所有红线之间的小矩形面积即可。
小矩形的面积就是高乘宽,宽就是两条红线之间的距离。高就是所有在两条红线内的矩形的高的区间合并的总高度,如图: 

 

 

#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;
}

 

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值