poj_3168 平面扫描

题目大意

给定平面上N个矩形的位置(给出矩形的左下角和右上角的坐标),这些矩形有些会有重叠,且重叠只会出现矩形的边重合全部或部分,矩形的顶点重合,而不会出现一个矩形的顶点位于另一个矩形的内部。 
    求出所有不重叠的矩形的个数。

题目分析

将每个矩形分成4个点,记录每个点所属的矩形id,对4*N个点进行按照x坐标和y坐标排序。 
    然后,沿着x方向进行扫描,对于相同的x,沿着该x坐标,从下向上找那些x坐标等于x的点的y坐标,判断该点所在矩形是否出现重合。若重合,则将该点所属的矩形记为重叠。 
    然后,沿着y方向进行扫描,对于相同的y,沿着该y坐标,从左到右找那些y坐标等于y的点的x坐标,判断该点所在矩形是否出现重合。若重合,则记其所在矩形为重叠。 
    怎么判断沿着某一x坐标或y坐标的那些点所在矩形是否重合呢?以沿着同一x坐标从下到上的那些点为例,用一个变量share_count表示当前时刻进入了几个矩形,从下到上遍历,若点A为某个矩形的下端点,则share_count加1,表示进入一个矩形,否则若A为某个矩形的上端点,share_count减1,表示从一个矩形离开。根据share_count >= 2,可知有矩形重叠,其他情况类似分析,画图可以很容易看出。

最后,遍历一遍所有的矩形,记下没有重叠的矩形个数即可。

实现(c++)

#include<stdio.h>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAX_N 200000

struct Point{
	int pos_x;	//x坐标
	int pos_y;	//y坐标
	int rect_id;	//矩形的id
	bool start_x;	//x方向是否是扫描时的入点
	bool start_y;	//方向是否是扫描时的入点
	Point(int p1=0, int p2=0, int id=0, bool sx=0, bool sy = 0) :
		pos_x(p1), pos_y(p2), rect_id(id), start_x(sx), start_y(sy){};
};
Point gPoint[4*MAX_N];

//按照x坐标排序比较函数,用于将 gSortOrder 排序,排序后的gSortOrder 为按照x从小到大排序的 gPoint的索引
bool Cmp_x(int p1, int p2){
	if (gPoint[p1].pos_x == gPoint[p2].pos_x)
		return gPoint[p1].pos_y < gPoint[p2].pos_y;
	return gPoint[p1].pos_x < gPoint[p2].pos_x;
}
//类似 Cmp_x
bool Cmp_y(int p1, int p2){
	if (gPoint[p1].pos_y == gPoint[p2].pos_y)
		return gPoint[p1].pos_x < gPoint[p2].pos_x;
	return gPoint[p1].pos_y < gPoint[p2].pos_y;
}
//排序后的gPoint索引。 按照x或者y坐标将 gPoint 排序后,gPoint中的点的位置。
int gSortOrder[4*MAX_N];
//判断矩形是否有重叠
bool gOverlap[MAX_N];
int main(){
	int n, a, b, c, d;
	while (scanf("%d", &n) != EOF){

		for (int i = 0; i < n; i++){
			scanf("%d %d %d %d", &a, &b, &c, &d);
			gPoint[4 * i] = Point(a, b, i, true, true);
			gPoint[4 * i + 1] = Point(a, d, i, true, false);
			gPoint[4 * i + 2] = Point(c, b, i, false, true);
			gPoint[4 * i + 3] = Point(c, d, i, false, false);
		}
		//n 变为点的数目
		n *= 4;
		for (int i = 0; i < n; i++){
			gSortOrder[i] = i;  //排序索引
		}

		memset(gOverlap, false, sizeof(gOverlap));

		//按照x坐标排序
		sort(gSortOrder, gSortOrder + n, Cmp_x);

		int i = 0;
		while(i < n){
			int j = i + 1, k = i;
			int share_count = 1;
			while (j < n && gPoint[gSortOrder[j]].pos_x == gPoint[gSortOrder[i]].pos_x){
				if (gPoint[gSortOrder[k]].pos_y == gPoint[gSortOrder[j]].pos_y){ //两条线重合的情形
					gOverlap[gPoint[gSortOrder[j]].rect_id] = true;
					gOverlap[gPoint[gSortOrder[k]].rect_id] = true;
				}
				if (gPoint[gSortOrder[j]].start_y){
					share_count++;
					if (share_count >= 2){	//说明有重合
						gOverlap[gPoint[gSortOrder[j]].rect_id] = true;
						gOverlap[gPoint[gSortOrder[j-1]].rect_id] = true;
					}
				}
				else{
					share_count--;
				}

				k = j++;
			}
			i = j;
		}
		//按照y坐标排序
		sort(gSortOrder, gSortOrder + n, Cmp_y);
		i = 0;
		while (i < n){
			int j = i + 1, k = i;
			int share_count = 1;
			while (j < n && gPoint[gSortOrder[j]].pos_y == gPoint[gSortOrder[i]].pos_y){
				if (gPoint[gSortOrder[k]].pos_x == gPoint[gSortOrder[j]].pos_x){
					gOverlap[gPoint[gSortOrder[j]].rect_id] = true;
					gOverlap[gPoint[gSortOrder[k]].rect_id] = true;
				}
				if (gPoint[gSortOrder[j]].start_x){
					share_count++;
					if (share_count >= 2){
						gOverlap[gPoint[gSortOrder[j]].rect_id] = true;
						gOverlap[gPoint[gSortOrder[j-1]].rect_id] = true;
					}
				}
				else{
					share_count--;
				}

				k = j++;
			}
			i = j;
		}
		int count = 0;

		//注意,这里的 n 变为 矩形的数目
		for (int i = 0; i < n/4; i++){
			if (!gOverlap[i])
				count++;
		}
		printf("%d\n", count);
	}
	return 0;
}
时间: 2024-10-14 14:00:18

poj_3168 平面扫描的相关文章

POJ 2932 Coneology (平面扫描)

Coneology Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3713   Accepted: 720 Description A student named Round Square loved to play with cones. He would arrange cones with different base radii arbitrarily on the floor and would admire

与平面和空间打交道的计算几何

计算几何基础 Jack Straws(POJ 1127) 原题如下: Jack Straws Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5494 Accepted: 2504 Description In the game of Jack Straws, a number of plastic or wooden "straws" are dumped on the table and players try

2017暑假集训前总结和规划

距离大一进来已经一年了啊,感觉还是啥也不会,哎,太差了,总结一下这一年都学了写什么吧! 大一寒假开始专题,刷过的有:dp,dfs和bfs,数论(gcd拓展gcd,欧拉定理等等,但是中国剩余定理没学,等复习的时候再学吧),并查集,最短路(bellman-fprd,dijkstra,floyd-warshall,spfa),最小生成树(prim,kruskal),线段树,二分三分 大一下学期有:拓扑排序,基础计算几何(直线线段相交,快速排除实验,跨立实验),矩阵快速幂,博弈基础(nim博弈,威佐夫博

poj 3293 Rectilinear polygon

Rectilinear polygon Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2125   Accepted: 249 Description Given is n points with integer coordinates in the plane. Is it is possible to construct a simple, that is non-intersecting, rectilinear

面试高级算法梳理笔记

面试高级算法梳理笔记 1.1 说明 本篇为<挑战程序设计竞赛(第2版)>读书笔记系列,旨在: 梳理算法逻辑 探索优化思路 深入代码细节 1.2 目录 原文首发于个人博客Jennica.Space,按算法难度划分为初中高三个级别,详细目录及链接如下: 初级篇 穷竭搜索 贪心 动态规划 数据结构 图论 数论 中级篇 二分搜索 常用技巧 数据结构(二) 动态规划(二) 网络流 计算几何 高级篇 数论(二) 博弈论 图论(二) 常用技巧(二) 智慧搜索 分治 字符串 1.3 题解 配套习题及详解同步发

类似支付宝扫描识别银行卡号的技术

类似支付宝扫描识别银行卡号的技术 新关键词:银行卡扫描识别,扫描银行卡卡号识别,银行卡号识别SDK,银行卡OCR识别 新银行卡扫描识别技术的应用背景 实际测试中手动输入16—19位银行卡号码,速度慢,易出错,用户体验非常差.为了提高在移动终端上输入银行卡号的速度和准确性,北京文通科技有限公司结合银行.保险.金融P2P及第三方支付等行业对自动识别银行卡号的迫切需求,推出银行卡号识别SDK,各类APP只需集成银行卡识别SDK后,便可自动识别银行卡号. 二.银行卡识别产品介绍 文通银行卡号识别SDK可

洛谷P1257 平面上的最接近点对 数学 分治 排序

来自洛谷上的题解 方法一: 先求第1个点与其余n-1个点的距离: 再求第2个点与其余n-2个点的距离: 再求第3个点与其余n-3个点的距离: ---------------- 再求第n-1个点与其余1个点的距离: 然后找出最小值. 如此的算法复杂度为O(n^2),显然不能满足本题的需要.但--貌似洛谷神机可以--过-- 欢迎朴素的同学挑战数据加强版新 方法二: 考虑以下分治算法: 设平面上的点都在点集S中,为了将S线性分割为大小大致相等的2个子集S1和S2,我们选取一垂直线l(方程:x=m)来作

仓库入仓-手机条码扫描

一般大型仓库入库时,会需要选择仓位 然而,当你拉着一车的商品要入仓时,会面临一个问题,那就是怎么对应上架单,来一个一个商品进行准确无误的入仓 针对这个问题,我们来做一个场景: 我的客户拿了200款饰品,要求录入公共仓 每一款商品都按照要求,粘贴了商品条码 并且系统已经为每个商品计算出了具体的存放仓位,就等着入仓了 小杨兴高采烈的拿着小推车到了货架旁,对着上架单里的第一个商品, 在小推车里翻来翻去,十几分钟过去了,仍然没有找到相应的商品... 时间过的很快,一下子1个小时过去,小杨还没有上架完成.

探索通用可编程数据平面

引言:相比传统网络数据平面,通用可编程数据平面让网络用户可以自定义数据包的完整处理流程,实现理想的协议无关网络数据处理.作为一种理想的SDN数据平面,通用可编程数据平面还不够完善,还需要在不断的尝试中摸索前进. 本文选自<重构网络:SDN架构与实现>. 相比传统网络数据平面,通用可编程数据平面让网络用户可以自定义数据包的完整处理流程,实现理想的协议无关网络数据处理.而当下的OpenFlow模型还无法成为一种完全的通用可编程数据转发模型,还无法实现协议无关的转发.只有实现了真正的通用可编程数据平