我有一个问题,最好用计算机屏幕上的窗口来说明:创建另一个窗口,尽可能大,不与任何现有窗口重叠。
换句话说:在有限表面(一张纸或一个屏幕)上给出一组N个矩形,找到可以在这些矩形之间拟合的最大矩形。 (坐标可以是任意的,因此位图在这里不是一个可行的解决方案。)
下图显示了三个矩形(黑色)和可以安装的最大矩形(红色)。
http://www.irstafoto.se/blogmtrl/rectangle-illustration.jpg
我为此编写了一个简单的算法,它考虑了矩形使用的所有x和y坐标对。遗憾的是,它是O(N ^ 5),因为在最坏的情况下,必须针对每个其他矩形检查每个矩形候选项以进行重叠。
有什么更好的吗?
max_area = 0; max_rect = nil xc = all rectangle x-coordinates [x1, ..., x6] in picture) yc = all rectangle y-coordinates (y1, ..., y6] in picture) xc = [0] + xc + [W]; /* W is width of area */ yc = [0] + yc + [H]; /* H is height of area */ sort(xc); sort(yc); for each x0 in xc for each x1 > x0 in xc for each y0 in yc for each y1 > y0 in yc r = rect(x0,y0,x1,y1) if (area(r) > max_area and !overlapping(r)) max_area = area(r) max_rect = r
答案 0 :(得分:0)
我的建议:
独立地对X和Y进行排序,以便您可以将所有角坐标映射到[0,2N]范围内的整数索引。
使用黑色填充二进制图像,其中空间由缩小坐标中的矩形占据。图像大小为(2N + 1)x(2N + 1)。
找到可放置在白色区域中的最大矩形。这可以在与图像区域成比例的时间内完成。 (参见文章“基于矩形列表的对象描述符:方法和算法”。)
然后对于每个最大矩形,在给定真实坐标的情况下计算实际面积,并保持最大
这应该是一个整体O(N²)程序。
答案 1 :(得分:0)
半四叉树方法怎么样?您可以创建一个具有9个属性的节点,矩形本身,4个矩形,其区域可用于节点当前矩形的北,南,东和西;最后4个节点,每个节点在相应的区域中具有子树。 Node类看起来像这样:
class node
{
public var nr:Rectangle;
public var sr:Rectangle;
public var wr:Rectangle;
public var er:Rectangle;
public var nn:node = null;
public var sn:node = null;
public var wn:node = null;
public var en:node = null;
public var rect:Rectangle;
}
创建新节点时,您应该使用包含当前矩形边的线条来剪切边界区域。这不是典型的四叉树。这里子节点的区域可能重叠。
另外两项基本行动。首先添加矩形。从第一个实心矩形开始,您可以创建一个节点,然后为每个剩余的矩形添加它们到树中。要向节点添加矩形,您应检查它是否与其任何区域重叠。如果是这样,将其剪辑到该区域并将其向下推到该节点。如果node为空(或null),则创建一个新节点。
最后找到一个最大的矩形。这是从根节点开始递归完成的。你应该得到覆盖所有4个区域的最大矩形。这很容易,因为您已经将它们作为节点的属性。但是有一个技巧 - 如果这个区域中有一个子节点,你应该使用这个节点最大的rect(这里是递归)。