最大矩形算法实现
我正在尝试用Python实现Dr. Dobbs的最大矩形算法(第四个例子)。大部分情况下它都能正常工作,但有一个特定的情况结果不对,我搞不清楚为什么。
这是我的源代码:
from collections import namedtuple
Point = namedtuple('Point', ('X', 'Y'))
#Y 0 1 2 X
arr = [[0, 0, 0, ], #0
[1, 0, 0, ], #1
[0, 0, 1, ], #2
]
def area(ll, ur):
if (ll.X < 0) or (ll.Y < 0) or (ur.X < 0) or (ur.Y < 0):
return 0.
return ((ur.X - ll.X) + 1) * ((ur.Y - ll.Y) + 1)
def update_cache(a, c, x):
M = len(a[0])
N = len(a)
for y in range(M):
if a[x][y] == 0:
c[y] = c[y] + 1
else:
c[y] = 0
def mrp(a):
best_ll = Point(-1, -1)
best_ur = Point(-1, -1)
M = len(a[0])
N = len(a)
c = [0 for x in range(M + 1)]
stack = []
for x in range(N-1, -1, -1):
update_cache(a, c, x)
width = 0
for y in range(M + 1):
if c[y] > width:
stack.append((y, width))
width = c[y]
if c[y] < width:
while True:
y0, w0 = stack.pop()
if (width * (y - y0)) > area(best_ll, best_ur):
best_ll = Point(x, y0)
best_ur = Point(x + width - 1, y - 1)
width = w0
if (c[y] >= width):
break
width = c[y]
if width == 0:
stack.append((y0, width))
return best_ll, best_ur
这是运行结果:
>>> mrp(arr)
(Point(X=0, Y=0), Point(X=1, Y=2))
你可以看到,第一个点的结果是错的,但我找不到问题出在哪里,也不知道为什么会出错。更改数组的内容后结果就对了。
编辑:我注意到我修改了数组的值,与文章中的不同。这改变了在update_cache中的比较,0代表清空,1代表保留。我想要的结果是(Point(X=0, Y=1), Point(X=1, Y=2))。
2 个回答
0
这里有一个从其他回答中修改过来的最佳解决方案:(让它稍微快一点,更容易阅读)
你可以查看这个链接了解更多:https://stackoverflow.com/a/30418912/2131849
arr = [
[0, 0, 0, ],
[1, 0, 0, ],
[0, 0, 1, ],
]
nrows = len(arr)
ncols = len(arr[0])
w = [[0]*ncols for n in range(nrows)]
h = [[0]*ncols for n in range(nrows)]
skip = 1
area_max = 0
rect = (0,0,0,0)
for r in range(nrows):
for c in range(ncols):
if arr[r][c] == skip: continue
h[r][c] = 1 if not r else h[r-1][c]+1
w[r][c] = 1 if not c else w[r][c-1]+1
minw = w[r][c]
for dh in range(h[r][c]):
minw = min(minw, w[r-dh][c])
area = (dh+1)*minw
if area > area_max[0]:
area_max = area
rect = (r-dh, c-minw+1, r, c)
print('area:', area_max)
print('(Point(X=%s, Y=%s), Point(X=%s, Y=%s))'%rect)
结果正是你想要的:
面积:4
(点(X=0, Y=1),点(X=1, Y=2))
4
最后的 stack.append 应该是:
stack.append((y0, w0))