.net – 获取具有障碍物的给定空间中的矩形的最大可能范围

我正在处理以下问题:

有一个带有空单元格的网格(空单元格显示为白色).此网格中的单个单元格已经被元素“占用”(元素以橙色显示).

现在我有一个矩形的起点(在这种情况下,第6行,第3列).此矩形应占用尽可能多的空闲单元格.矩形应停在橙色元素或网格结束时.

附带的屏幕截图显示了2个网格场景及其解决方案

左方案将返回

width = 2
height = 5

正确的方案将会回归

width = 1
height = 5

我已经尝试了很多次来编写一个简单,简单的代码,它将返回该矩形的最大宽度和高度,但最后我总是得到一个冗长而丑陋的代码.

有没有一个干净,简短的数学解决方案,或者这是一个简单的问题,并不像它在一开始看起来那么容易?

谢谢.
《.net – 获取具有障碍物的给定空间中的矩形的最大可能范围》.

最佳答案 用0-1矩阵表示网格,其中1对应于障碍物.

如果网格是m×n并且(a,b)是起始单元的基于0的行和列索引,则width = n-b表示从该单元开始的矩形的最大可能宽度,而与任何障碍无关.这是当前的宽度.现在,开始从该单元格向下扫描列,直到遇到底边或障碍物.对于该列中的每个单元格,开始向右扫描,直到达到障碍物或当前宽度.如果首先遇到障碍物,请减小当前宽度.将当前宽度附加到宽度列表(当前宽度是否已减小).

在此阶段,您有一个宽度列表,每个可能的高度都有一个宽度.只需扫描此列表,将每个宽度乘以相应的高度(这将是1基于0的列表索引).返回最大化产品高度*宽度的对(高度,宽度).

Python实现:

def find_max_rect(grid,a,b):
    if grid[a][b] == 1: return (0,0)
    m = len(grid) #number of rows
    n = len(grid[0]) #number of columns
    width = n-b #maximum possible width given starting column
    widths = [] 
    i = a
    while i < m and grid[i][b] == 0:
        #scan right from (i,b+1) until a 1 or current width is hit
        for j in range(b+1,b+width):
            if grid[i][j] == 1:
                #an obstacle forces width to contract
                width = j-b #number of steps before obstacle
                break #out of inner loop
        widths.append(width)
        i += 1      
    max_area = 0
    max_at = -1
    for i,width in enumerate(widths):
        if (i+1)*width > max_area:
            max_area = (i+1)*width
            max_at = i
    return (max_at + 1,widths[max_at])

测试如下:

test_grid = [[1,0,1,1,0],
             [0,1,0,0,0],
             [0,1,0,0,0],
             [0,1,0,0,0],
             [0,0,0,1,0],
             [0,0,0,1,0],
             [0,0,0,0,1],
             [0,0,0,0,0],
             [1,0,0,0,0],
             [0,0,0,0,1],
             [0,1,0,0,0]]

print(find_max_rect(test_grid,6,2)) #prints (5,2)

在编辑:我意识到没有理由存储候选宽度只是为了迭代它们一次.相反,您可以随时跟踪最佳区域.以下代码功能相同但效率更高:

def find_max_rect(grid,a,b):
    if grid[a][b] == 1: return (0,0)
    m = len(grid) #number of rows
    n = len(grid[0]) #number of columns
    current_height = 0
    current_width = n - b #maximum possible width given starting column
    max_area = 0
    best_height, best_width = current_height, current_width

    i = a
    while i < m and grid[i][b] == 0:
        current_height += 1
        #scan right from (i,b + 1) until a 1 or current width is hit
        for j in range(b + 1,b + current_width):
            if grid[i][j] == 1:
                #an obstacle forces width to contract
                current_width = j - b #number of steps before obstacle
                break
        #decide if the best should be adjusted
        current_area = current_height * current_width
        if  current_area > max_area:
            best_area, best_height, best_width = current_area, current_height, current_width
        i+=1
    return best_height, best_width
点赞