您将获得一个长度'L'和广度'B'的矩形。将矩形视为包含 LxB 单元格的网格。您还可以获得那些被认为是洞的细胞的位置。
任务是找到这个给定矩形中的最大矩形,使得这个矩形不包含任何孔。
我知道我可以使用蛮力来做到这一点,但这需要花费太多时间。还有其他更快的算法吗?
PS:“最大矩形”表示具有最大面积的矩形。
答案 0 :(得分:3)
答案 1 :(得分:1)
这是一种基于DP的方法..不一定比论文中的方法更好,但更容易理解。
创建一个memoization表,其中x和y值对应于单元格的端点。 像这样填写表格。
dp [x] [y] = max(increment_x(dp [x-1] [y]),
increment_y( dp[x][y-1] ) ;
增量函数将不增量,如果增加坐标会增加一个孔,如(d)...并且只返回max(x-,y-)。
注意:当递增时,导致完全吞没一个孔,如e)..可能需要比较两个矩形,一个在孔之前和一个在孔之后,并且在关系上可以保留更多自由的人。
您还可以通过仅采用“有效格点”而非每lattice point步骤进行优化。
这是一个原创想法,可能有缺陷。点数:)
答案 2 :(得分:0)
您可以尝试扫描线方法。
首先使用父矩形的一条边上的可能起始位置的位置和大小初始化一个列表。现在,您将保存所有可能的矩形,它们具有以下属性:start,end,width。宽度为0,开头为。
现在你迭代并在每一步中检查以下内容:
最后只需检查最大的矩形列表。如果你的内存非常有限,你可以通过保留最大的非活动矩形来改进解决方案
算法的一个小表示,其中x表示一个洞:
-----
|x |
| |
-----
初始:
1,2,0, active
第1步:
1,2,1 active
0,1,0 active
第2步:
1,2,2 inactive
0,1,1 inactive
答案 3 :(得分:0)
这是另一种方法: -
create list of rectangles
add one rectangle, size LxB
for each hole
get rectangles containing hole
remove rectangles from list
for each rectangle
create 0-4 child rectangles
add child rectangles to list
find largest rectangle in list
创建子矩形: -
|-------| parent rectangle with hole under consideration (x)
| |
| x |
| |
|-------|
创建四个子矩形: -
|-|-----|
|.| |
|.|x |
|.| |
|-|-----|
|---|---|
| |...|
| x|...|
| |...|
|---|---|
|-------|
|-------|
| x |
| |
|-------|
|-------|
| |
| x |
|-------|
|-------|
如果孔与边缘相邻,则子项的宽度或高度为零,因此不会将其添加到列表中。
不知道为什么这被投了票。无论如何,这是C#中的一个实现: -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Diagnostics;
namespace LargestRectangle
{
class Program
{
static Rectangle FindLargestRectangle(Rectangle bounds, List<Point> holes)
{
LinkedList<Rectangle>
rectangles = new LinkedList<Rectangle>();
rectangles.AddLast(bounds);
foreach (Point hole in holes)
{
for (LinkedListNode<Rectangle> rect = rectangles.First, next=null; rect != null; rect = next)
{
next = rect.Next;
if (rect.Value.Contains(hole))
{
rectangles.Remove(rect);
if (rect.Value.Left < hole.X)
{
rectangles.AddFirst(new Rectangle(rect.Value.Left, rect.Value.Top, hole.X - rect.Value.Left, rect.Value.Height));
}
if (rect.Value.Right - 1 > hole.X)
{
rectangles.AddFirst(new Rectangle(hole.X + 1, rect.Value.Top, rect.Value.Right - hole.X - 1, rect.Value.Height));
}
if (rect.Value.Top < hole.Y)
{
rectangles.AddFirst(new Rectangle(rect.Value.Left, rect.Value.Top, rect.Value.Width, hole.Y - rect.Value.Top));
}
if (rect.Value.Bottom - 1 > hole.Y)
{
rectangles.AddFirst(new Rectangle(rect.Value.Left, hole.Y + 1, rect.Value.Width, rect.Value.Bottom - hole.Y - 1));
}
}
}
}
Rectangle
largest = new Rectangle(0, 0, 0, 0);
int
max_area = 0;
foreach (Rectangle rect in rectangles)
{
int
area = rect.Width * rect.Height;
if (area > max_area)
{
largest = rect;
max_area = area;
}
}
return largest;
}
static void Main(string[] args)
{
int
max_holes = 100,
size = 50;
Rectangle
bounds = new Rectangle(0, 0, size, size);
List<Point>
holes = new List <Point> ();
Random
random = new Random ();
for (int i = 0; i < max_holes; ++i)
{
holes.Add(new Point(random.Next(size), random.Next(size)));
}
List<string>
area = new List<String>();
for (int i = 0; i < size; ++i)
{
area.Add(new String('.', size));
}
foreach (Point p in holes)
{
area[p.Y] = area[p.Y].Substring(0, p.X) + '*' + area[p.Y].Substring(p.X + 1);
}
Console.WriteLine("Map:-");
Console.WriteLine("");
foreach (string s in area)
{
Console.WriteLine(s);
}
Stopwatch
execution_time = new Stopwatch();
execution_time.Start();
Rectangle
largest_rect = FindLargestRectangle(bounds, holes);
execution_time.Stop();
for (int y = largest_rect.Top; y < largest_rect.Bottom; ++y)
{
area[y] = area[y].Substring(0, largest_rect.Left) + new string('#', largest_rect.Width) + area[y].Substring(largest_rect.Right); string
}
Console.WriteLine("");
Console.WriteLine("Map:-");
Console.WriteLine("");
foreach (string s in area)
{
Console.WriteLine(s);
}
Console.WriteLine("");
Console.WriteLine("Largest rectangle: (" + largest_rect.Left + "," + largest_rect.Top + ")-(" + (largest_rect.Right - 1) + "," + (largest_rect.Bottom - 1) + ")");
Console.WriteLine("Execution time = " + execution_time.ElapsedMilliseconds);
}
}
}
使用DevStudio 2008构建。
在我的机器上,50x50网格中的100个孔需要59ms。我最初使用List&lt; Rectangle&gt;而不是LinkedList&lt; Rectangle&gt;但这花了1000多秒!