找到一组最大的连片矩形覆盖多个领域多个、矩形、领域、最大

2023-09-10 22:44:05 作者:一生一个你

我工作的一个名为 Quickfort 的游戏矮人要塞。 Quickfort变成小号preadsheets以CSV / XLS格式转换为一系列的矮人要塞命令开展以游戏内绘制蓝图。

I'm working on a tool called Quickfort for the game Dwarf Fortress. Quickfort turns spreadsheets in csv/xls format into a series of commands for Dwarf Fortress to carry out in order to plot a "blueprint" within the game.

目前我正在试图以最佳方式解决的区域,绘制问题2.0版本这个工具。

I am currently trying to optimally solve an area-plotting problem for the 2.0 release of this tool.

考虑以下蓝图,它定义为一个二维网格绘图命令。网格中的每个单元要么被挖出来(D),渠道(C),或左unplotted(。)。任何数量的不同的绘图命令可能是present在实际应用中。

Consider the following "blueprint" which defines plotting commands for a 2-dimensional grid. Each cell in the grid should either be dug out ("d"), channeled ("c"), or left unplotted ("."). Any number of distinct plotting commands might be present in actual usage.

. d . d c c
d d d d c c
. d d d . c
d d d d d c
. d . d d c

要最大限度地减少了需要发送到矮人要塞的指令数,我想找到一组可以形成完全覆盖最大的连续矩形的,还是阴谋,所有的plottable细胞。为有效,所有的给定矩形的细胞必须包含相同的命令。

To minimize the number of instructions that need to be sent to Dwarf Fortress, I would like to find the set of largest contiguous rectangles that can be formed to completely cover, or "plot", all of the plottable cells. To be valid, all of a given rectangle's cells must contain the same command.

这是比Quickfort 1.0更快的方法了:单独绘制每一个细胞作为一个1x1的矩形。 此影片显示了这两个版本之间的性能差异。

This is a faster approach than Quickfort 1.0 took: plotting every cell individually as a 1x1 rectangle. This video shows the performance difference between the two versions.

有关上述蓝图,该解决方案是这样的:

For the above blueprint, the solution looks like this:

. 9 . 0 3 2
8 1 1 1 3 2
. 1 1 1 . 2
7 1 1 1 4 2
. 6 . 5 4 2

每个编号相同的矩形上方表示连续的矩形。最大的矩形采取precedence过,可能还可以形成在各自的领域较小的矩形。编号/矩形的顺序并不重要。

Each same-numbered rectangle above denotes a contiguous rectangle. The largest rectangles take precedence over smaller rectangles that could also be formed in their areas. The order of the numbering/rectangles is unimportant.

我的目前的做法是重复的。在每次迭代中,我建立,可以从每个网格的plottable细胞通过在从小区中的所有4个方向延伸而形成的最大的矩形的列表。第一排序列表中最大的,我首先发现的最大的矩形,其下方的单元格标记为策划,并记录在列表中的矩形。在绘制每个矩形,其下方的单元格进行检查,以确保它们没有绘制(重叠一个previous图)。然后,我们再次开始,发现可以形成最大的其余矩形和绘图,直到所有细胞已被描绘为一些矩形的一部分。

My current approach is iterative. In each iteration, I build a list of the largest rectangles that could be formed from each of the grid's plottable cells by extending in all 4 directions from the cell. After sorting the list largest first, I begin with the largest rectangle found, mark its underlying cells as "plotted", and record the rectangle in a list. Before plotting each rectangle, its underlying cells are checked to ensure they are not yet plotted (overlapping a previous plot). We then start again, finding the largest remaining rectangles that can be formed and plotting them until all cells have been plotted as part of some rectangle.

我认为这种做法略多于一个愚蠢的强力搜索优化,但我浪费了大量的周期(重)计算细胞的最大的矩形,并检查底层细胞的状态。

I consider this approach slightly more optimized than a dumb brute-force search, but I am wasting a lot of cycles (re)calculating cells' largest rectangles and checking underlying cells' states.

目前,这个矩形发现日常需要的大部分份额的工具的总运行时间的,特别是对于大型的蓝图。我已通过仅考虑这似乎形成矩形的角落(使用一些邻近小区启发式其中并非总是正确测定)从细胞中的矩形牺牲一些精度为求速度的。由于这种优化,我现在的code实际上并没有正确地产生上述的解决方案,但它是足够接近的结果。

Currently, this rectangle-discovery routine takes the lion's share of the total runtime of the tool, especially for large blueprints. I have sacrificed some accuracy for the sake of speed by only considering rectangles from cells which appear to form a rectangle's corner (determined using some neighboring-cell heuristics which aren't always correct). As a result of this 'optimization', my current code doesn't actually generate the above solution correctly, but it's close enough.

更广泛地说,我认为最大的矩形,第一个是足够好的方式为这个应用程序的目标。不过,我观察到,如果我们的目标是不是找到的最低组矩形的(最少数量),以完全覆盖多个领域,解决的办法是这样的,而不是:

More broadly, I consider the goal of largest-rectangles-first to be a "good enough" approach for this application. However I observe that if the goal is instead to find the minimum set (fewest number) of rectangles to completely cover multiple areas, the solution would look like this instead:

. 3 . 5 6 8
1 3 4 5 6 8
. 3 4 5 . 8
2 3 4 5 7 8
. 3 . 5 7 8

这第二个目标实际上是重新presents的问题更优化的解决方案,因为较少的矩形通常是指发送到矮人要塞较少的命令。然而,这种方法令我更接近NP难的,根据我有限的数学知识。

This second goal actually represents a more optimal solution to the problem, as fewer rectangles usually means fewer commands sent to Dwarf Fortress. However, this approach strikes me as closer to NP-Hard, based on my limited math knowledge.

观看影片,如果你想更好地了解总体战略;我还没有涉及其他方面的Quickfort的过程中,如发现最短光标路径,描绘所有的矩形。可能有一个解决这个问题,即相干地组合这些多种策略

Watch the video if you'd like to better understand the overall strategy; I have not addressed other aspects of Quickfort's process, such as finding the shortest cursor-path that plots all rectangles. Possibly there is a solution to this problem that coherently combines these multiple strategies.

任何形式的帮助将AP preciated。

Help of any form would be appreciated.

推荐答案

我发现的文件的快速算法来划分简单直线多边形从圣元武萨尔塔杰萨尼的,这可能是你的兴趣。在您的例子有字符'D'的区域形成一个直线多边形,也是地区'C'和'。'。本文包括算法的无孔​​的简单直线多边形的。

I found the paper Fast Algorithms To Partition Simple Rectilinear Polygons from San-Yuan Wu and Sartaj Sahni, which could be of interest to you. In your example the region with character 'd' forms a rectilinear polygon, also the regions with 'c' and '.'. This paper includes algorithms for hole-free simple rectilinear polygons.

如果一个多边形,包括孔,还有带O运行(N ^ 3/2 log n)的时间,因为JM凯尔算法在纸上的多边形分解第11个州。

If a polygon includes holes, there are algorithms running with O(n^3/2 log n) time, as JM Keil in the paper Polygon Decomposition on page 11 states.

如果减少在分区过程引入的线段的总长度是其他优化标准的,问题就变得NP完全如果多边形包含孔(第12页)。对于这些问题的近似算法存在(纸是指与这样的算法的论文)。如果多边形不包含孔有一个为O(n ^ 4)时间的算法。

If minimizing the total length of the line segments introduced in the partitioning process is the other optimization criterion, the problem becomes NP-complete if the polygon contains holes (page 12). For these problems approximation algorithms exist (the paper refers to papers with such algorithms). If the polygon doesn't contain holes there is an O(n^4) time algorithm.