有一个任意大小的二维网格。 (例如1000 * 1000)
这是模式:
给定的输入是四个整数:x y w h,表示每个矩形左下角的(x,y)坐标及其宽度和高度。
具有共享边缘或重叠的矩形定义为已连接。
一组连接的矩形被定义为群集。
每个单位单元格上的矩形数量定义为厚度。
所以问题要求计算: 1.最大厚度 2.集群数量 3.单个群集的最大群集元素数 4.单个群集的最大区域
例如,在上图中,最大厚度为3,并且有2个簇。一个簇由3个矩形组成,其面积为44.另一个簇中的元素数为4,区域为30.因此,具有最大簇元素数的簇为4,最大簇区域为44。
我的解决方案非常天真。我使用了一个2-d int数组来表示网格。读取输入时,我只是增加相应单元格中的数字。读完所有输入后,我使用深度优先搜索来决定聚类。
问题是我的算法很慢并且在给定大输入时很快就会无法使用(例如当网格大小超过1000 * 1000时)
所以我想知道有没有有效的数据结构和算法来解决这个问题?
答案 0 :(得分:1)
读完所有输入后,我使用深度优先搜索来决定群集。
您不需要这样做 - 您可以在阅读输入时决定群集,就像您决定厚度一样。
对于每个单元格,跟踪它所属的集群。在迭代与读取矩形对应的网格单元格时,跟踪它们所属的聚类。将在此遍历期间找到的所有群集合并到单个群集中。您可以使用Disjoint-set数据结构在非常接近恒定的时间内有效地执行此操作。
但是,sweep line algorithm可能会更好地解决您的整个问题。
答案 1 :(得分:1)
我认为您刚刚使用2D AABB结构描述了空间分区。
输入网格被抛入树中并任意定向。树的目的是排序。
您可能需要扩展树的功能以满足您的需求(例如,连接,跟踪群集,图层/厚度)。
用于包含2D AABB的空间分区树可以加宽,展开或叶缓存,以有效减少访问时间。
视频游戏中的2D物理引擎使用它可以在任意大(大致无限)的网格大小上轻松有效地管理数百到数千个任意形状的对象碰撞。它们的处理可以通过OpenCL(用于CPU和GPU)或其他GPGPU技术等技术加速。
请参阅AABBs上的这篇维基百科文章。
有关使用(二进制)树进行空间分区的一般概念,请参阅BSPs上的这篇维基百科文章。
在quadtrees上查看这篇维基百科文章作为可能更容易实现的高阶树概念,如果一切都是AABB,甚至可能更快,因为它的宽度要宽4倍。你也可以压扁甚至更高阶的树木,尽管对于2D空间来说,这些效益大多数似乎是四边形。
请参阅collision detection上的这篇维基百科文章,了解确定连接和群集的方法。
请参阅splay trees上的这篇维基百科文章,了解有关推广和扩大树木的好处的想法。
答案 2 :(得分:1)
我的建议是结合当前给出的另外两个答案:使用一些空间数据结构(如AABB树或四叉树)来存储到目前为止已处理的所有矩形,以便您可以快速找到连接的矩形;然后将连接的集群存储在union find或disjoint集数据结构中。
一旦您处理了所有矩形,您就可以在线性时间内回答问题2和3。问题1(最大厚度)有点棘手;如果您不小心,如果所有矩形重叠,您最终可能会进行二次数重叠测试。同样的答案4。
因此,当您输入与空间数据结构重叠的矩形时,最佳解决方案可能是将其拆分为不变厚度的不相交部分。然后1和4也很容易回答相对较快。