题目大意

给定平面上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++)

  1. #include<stdio.h>
  2. #include<vector>
  3. #include<string.h>
  4. #include<algorithm>
  5. using namespace std;
  6. #define MAX_N 200000
  7.  
  8. struct Point{
  9. int pos_x; //x坐标
  10. int pos_y; //y坐标
  11. int rect_id; //矩形的id
  12. bool start_x; //x方向是否是扫描时的入点
  13. bool start_y; //方向是否是扫描时的入点
  14. Point(int p1=0, int p2=0, int id=0, bool sx=0, bool sy = 0) :
  15. pos_x(p1), pos_y(p2), rect_id(id), start_x(sx), start_y(sy){};
  16. };
  17. Point gPoint[4*MAX_N];
  18.  
  19. //按照x坐标排序比较函数,用于将 gSortOrder 排序,排序后的gSortOrder 为按照x从小到大排序的 gPoint的索引
  20. bool Cmp_x(int p1, int p2){
  21. if (gPoint[p1].pos_x == gPoint[p2].pos_x)
  22. return gPoint[p1].pos_y < gPoint[p2].pos_y;
  23. return gPoint[p1].pos_x < gPoint[p2].pos_x;
  24. }
  25. //类似 Cmp_x
  26. bool Cmp_y(int p1, int p2){
  27. if (gPoint[p1].pos_y == gPoint[p2].pos_y)
  28. return gPoint[p1].pos_x < gPoint[p2].pos_x;
  29. return gPoint[p1].pos_y < gPoint[p2].pos_y;
  30. }
  31. //排序后的gPoint索引。 按照x或者y坐标将 gPoint 排序后,gPoint中的点的位置。
  32. int gSortOrder[4*MAX_N];
  33. //判断矩形是否有重叠
  34. bool gOverlap[MAX_N];
  35. int main(){
  36. int n, a, b, c, d;
  37. while (scanf("%d", &n) != EOF){
  38.  
  39. for (int i = 0; i < n; i++){
  40. scanf("%d %d %d %d", &a, &b, &c, &d);
  41. gPoint[4 * i] = Point(a, b, i, true, true);
  42. gPoint[4 * i + 1] = Point(a, d, i, true, false);
  43. gPoint[4 * i + 2] = Point(c, b, i, false, true);
  44. gPoint[4 * i + 3] = Point(c, d, i, false, false);
  45. }
  46. //n 变为点的数目
  47. n *= 4;
  48. for (int i = 0; i < n; i++){
  49. gSortOrder[i] = i; //排序索引
  50. }
  51.  
  52. memset(gOverlap, false, sizeof(gOverlap));
  53.  
  54. //按照x坐标排序
  55. sort(gSortOrder, gSortOrder + n, Cmp_x);
  56.  
  57. int i = 0;
  58. while(i < n){
  59. int j = i + 1, k = i;
  60. int share_count = 1;
  61. while (j < n && gPoint[gSortOrder[j]].pos_x == gPoint[gSortOrder[i]].pos_x){
  62. if (gPoint[gSortOrder[k]].pos_y == gPoint[gSortOrder[j]].pos_y){ //两条线重合的情形
  63. gOverlap[gPoint[gSortOrder[j]].rect_id] = true;
  64. gOverlap[gPoint[gSortOrder[k]].rect_id] = true;
  65. }
  66. if (gPoint[gSortOrder[j]].start_y){
  67. share_count++;
  68. if (share_count >= 2){ //说明有重合
  69. gOverlap[gPoint[gSortOrder[j]].rect_id] = true;
  70. gOverlap[gPoint[gSortOrder[j-1]].rect_id] = true;
  71. }
  72. }
  73. else{
  74. share_count--;
  75. }
  76.  
  77. k = j++;
  78. }
  79. i = j;
  80. }
  81. //按照y坐标排序
  82. sort(gSortOrder, gSortOrder + n, Cmp_y);
  83. i = 0;
  84. while (i < n){
  85. int j = i + 1, k = i;
  86. int share_count = 1;
  87. while (j < n && gPoint[gSortOrder[j]].pos_y == gPoint[gSortOrder[i]].pos_y){
  88. if (gPoint[gSortOrder[k]].pos_x == gPoint[gSortOrder[j]].pos_x){
  89. gOverlap[gPoint[gSortOrder[j]].rect_id] = true;
  90. gOverlap[gPoint[gSortOrder[k]].rect_id] = true;
  91. }
  92. if (gPoint[gSortOrder[j]].start_x){
  93. share_count++;
  94. if (share_count >= 2){
  95. gOverlap[gPoint[gSortOrder[j]].rect_id] = true;
  96. gOverlap[gPoint[gSortOrder[j-1]].rect_id] = true;
  97. }
  98. }
  99. else{
  100. share_count--;
  101. }
  102.  
  103. k = j++;
  104. }
  105. i = j;
  106. }
  107. int count = 0;
  108.  
  109. //注意,这里的 n 变为 矩形的数目
  110. for (int i = 0; i < n/4; i++){
  111. if (!gOverlap[i])
  112. count++;
  113. }
  114. printf("%d\n", count);
  115. }
  116. return 0;
  117. }

poj_3168 平面扫描的更多相关文章

  1. POJ 2932 平面扫描 /// 判断圆的包含关系

    题目大意: 平面上有n个两两不相交的圆,给定圆的圆心(x,y)和半径 r 求所有最外层的 即 不包含于其他圆内部的圆 挑战258页 平面扫描 记录所有圆的左端和右端 排序后 逐一扫描 将到当前圆为止的 ...

  2. 基于正向扫描的并行区间连接平面扫描算法(IEEE论文)

    作者: Panagiotis Bouros ∗Department of Computer ScienceAarhus University, Denmarkpbour@cs.au.dkNikos M ...

  3. poj3168 Barn Expansion【计算几何 平面扫描】

    Farmer John has N (1 <= N <= 25,000) rectangular barns on his farm, all with sides parallel to ...

  4. TTTTTTTTTTTTTTT poj 2932 Coneology 平面扫描+STL

    题目链接 题意:有n个圆,圆之间不存在相交关系,求有几个不被其他任何圆包含的圆,并输出圆的编号: #include <iostream> #include <cstdio> # ...

  5. 计算几何值平面扫面poj2932 Coneology

    Coneology Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4097   Accepted: 859 Descript ...

  6. Cesium专栏-雷达遮罩动态扫描(附源码下载)

    Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...

  7. 3000本IT书籍下载地址

    http://www.shouce.ren/post/d/id/112300    黑客攻防实战入门与提高.pdfhttp://www.shouce.ren/post/d/id/112299    黑 ...

  8. NOIP2014-10-30模拟赛

    T1:逗比三角形 [题目描述] 小J是一名OI退役滚粗文化课选手,他十分喜欢做题,尤其是裸题.他现在有一个二维盒子和一些二维三角形,这个盒子拥有无限的高度和L的宽度.而且他的三角形也都是一些锐角三角形 ...

  9. 计算几何-凸包-toleft test

    toLeftTest toLeftTest是判断一个点是否在有向直线左侧的算法. 当点s位于向量pq左侧时,toLeftTest返回true.当点s位于向量pq右侧时,toLeftTest返回fals ...

随机推荐

  1. 【C#】List列表的深复制,引用类型深复制

    需求:深复制该列表. Student实体类: public class Student { public string Name { get; set; } public int Age { get; ...

  2. 【转】【C#】实现依赖注入

    1. 问题的提出 开发中,尤其是大型项目的开发中,为了降低模块间.类间的耦合关系,比较提倡基于接口开发,但在实现中也必须面临最终是“谁”提供实体类的问题.Martin Fowler在<Inver ...

  3. java后台json如何传递到jsp中解析

    需求:  系统前端jsp使用的是easyUi的datagrid展示了一些任务信息,任务信息中有个状态信息显示的值是数字, 需要根据后台保存的映射关系,将状态显示为描述信息. 原来的jsp前端显示: 解 ...

  4. scala实现彩票算法

    scala实现彩票算法 (1)具体实现代码如下: package hw1 import scala.util.control._ /** * @author BIGDATA */ object Cp ...

  5. NLog 配置与使用

    有段时间没写博客了,过年放假,一直在弄CMS.什么都自己写了一遍,今天写写NLog,之前一用的log4net,感觉配置起来还是有些麻烦. NuGet 添加组件 配置 NLog.config <? ...

  6. tomcat http协议与ajp协议

    AJP13是定向包协议.因为性能原因,使用二进制格式来传输可读性文本.WEB服务器通过 TCP连接和SERVLET容器连接.为了减少进程生成 socket的花费,WEB服务器和SERVLET容器之间尝 ...

  7. HTTP协议详解(文档)

    目录引言................................................................................................ ...

  8. 【转】java基本数据类型vs封装数据类型

    1.基本概念 说java是面向对象的语言是正确的,但是她不纯,基本数据类型就不是对象. 基本数据类型可以大致分为三类:数据型:int.short.long.byte.float.double字符型:c ...

  9. 结合使用 Oracle 和 Ruby on Rails 的补充

    本文是对此文的补充: 结合使用 Oracle 和 Ruby on Rails http://www.oracle.com/technetwork/cn/tutorials/rubyrails-0959 ...

  10. thinkphp 查询指定分类下的文章

    $list = $Dao->query("SELECT xp_wztj.bt,xp_wztj.time,xp_wztj.gjz,xp_wztj.wz,xp_wzfl.name FROM ...