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;
}
poj_3168 平面扫描的更多相关文章
- POJ 2932 平面扫描 /// 判断圆的包含关系
题目大意: 平面上有n个两两不相交的圆,给定圆的圆心(x,y)和半径 r 求所有最外层的 即 不包含于其他圆内部的圆 挑战258页 平面扫描 记录所有圆的左端和右端 排序后 逐一扫描 将到当前圆为止的 ...
- 基于正向扫描的并行区间连接平面扫描算法(IEEE论文)
作者: Panagiotis Bouros ∗Department of Computer ScienceAarhus University, Denmarkpbour@cs.au.dkNikos M ...
- poj3168 Barn Expansion【计算几何 平面扫描】
Farmer John has N (1 <= N <= 25,000) rectangular barns on his farm, all with sides parallel to ...
- TTTTTTTTTTTTTTT poj 2932 Coneology 平面扫描+STL
题目链接 题意:有n个圆,圆之间不存在相交关系,求有几个不被其他任何圆包含的圆,并输出圆的编号: #include <iostream> #include <cstdio> # ...
- 计算几何值平面扫面poj2932 Coneology
Coneology Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4097 Accepted: 859 Descript ...
- Cesium专栏-雷达遮罩动态扫描(附源码下载)
Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...
- 3000本IT书籍下载地址
http://www.shouce.ren/post/d/id/112300 黑客攻防实战入门与提高.pdfhttp://www.shouce.ren/post/d/id/112299 黑 ...
- NOIP2014-10-30模拟赛
T1:逗比三角形 [题目描述] 小J是一名OI退役滚粗文化课选手,他十分喜欢做题,尤其是裸题.他现在有一个二维盒子和一些二维三角形,这个盒子拥有无限的高度和L的宽度.而且他的三角形也都是一些锐角三角形 ...
- 计算几何-凸包-toleft test
toLeftTest toLeftTest是判断一个点是否在有向直线左侧的算法. 当点s位于向量pq左侧时,toLeftTest返回true.当点s位于向量pq右侧时,toLeftTest返回fals ...
随机推荐
- Android——数据存储:手机外部存储 SD卡存储
xml <EditText android:layout_width="match_parent" android:layout_height="wrap_cont ...
- 轻量级ORM框架Dapper应用四:使用Dapper返回多个结果集
使用Dapper的QueryMultiple方法可以一次执行多条SQL语句,返回多个结果集,代码如下 using System; using System.Collections.Generic; u ...
- AJAX 实时读取输入文本(php)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 控件EditText
(一)监听EditText输入内容变化 EditText.addTextChangedListener(textWatcher); //EditText change listener //此方 ...
- 如今在 Internet 上流传的“真正”的程序员据说是这样的
如今在 Internet 上流传的“真正”的程序员据说是这样的: (1) 真正的程序员没有进度表,只有讨好领导的马屁精才有进度表,真正的程序员会让 领导提心吊胆. (2) 真正的程序员不写使用说明书, ...
- 在windows下编译ffmpeg
编译ffmpeg,我在网上找了很多相关的方法,但最后都没编译成功. 所以下面就记录下自己的编译方法吧,留着以后编译的时候做参考. 1.首先,下载编译工具MinGW+Msys,搭建编译环境.工具下载地址 ...
- 关于HTTP keep-alive的实验(转至 http://my.oschina.net/flashsword/blog/80037)
前面一篇文章提到,HTTP1.1中持久连接已经是默认配置,除非设置Connection为close,否则默认都会进行持久连接.但是我们知道事实标准跟教科书还是可能会有一定差距的,所以不妨自己尝试一下. ...
- R语言低级绘图函数-title
title 函数用来在一张图表上添加标题 基本用法: main 表示主标题,通常位于图像的上方, sub 表示副标题,位于图像的下方, xlab 表示x轴的标签,ylab 表示y轴的标签 par(om ...
- oracle的varchar2和clob类型在hibernate中使用
1.在oracle中 varchar2的最大长度为4000 bytes,即varchar2(4000),最多能储存2000个汉子或4000位的数字字母.当储存值超过时可以使用clob(Characte ...
- 小明A+B(杭电2096)
/*小明A+B Problem Description 小明今年3岁了, 如今他已经可以认识100以内的非负整数, 而且可以进行100以内的非负整数的加法计算. 对于大于等于100的整数, 小明仅保留 ...