我知道这个挑战已有一年多了,但是我只是在“未回答”中发现了这个挑战,对我来说看起来很有趣。
假设“根”单元格的数量是每个区域中唯一的有效数字(可从示例中推导),这是我的回溯解决方案:
from itertools import*
def f(a):
D=len(a[0])+1;S={D*r+c for r in range(len(a))for c in range(D-1)if a[r][c]};s=[{x,*t}for x in S for t in combinations({x-D,x-1,x+1,x+D}&S,a[x//D][x%D]-1)]
def B(s,S,d=1):
if{0}>S:return a
if[]==s:return 0
h,*t=s
if h<=S:
for x in h:a[x//D][x%D]=d
return h<=S and B(t,S-h,d+1)or B(t,S,d)
return B(s,S)
在线尝试!
输入格式是2D整数列表,空白为零,输出格式也是2D整数列表,每个数字代表一个区域。区域号从1开始;零为空白单元格保留(与输入相同)。如果给定的输入不可解,则该函数返回单个零(伪造的值)。
例如,将测试用例5输入为
[[2,3,2],
[3,4,3],
[0,4,0],
[3,3,3],
[2,3,2],
[0,3,0]]
输出是
[[1,1,1],
[2,2,2],
[0,2,0],
[3,4,5],
[3,4,5],
[0,4,0]]
取消评论,并附上评论:
from itertools import*
def f(a):
# Rows, cols, fake-cols to prevent neighbors wrap around
R,C=len(a),len(a[0]);D=C+1
# All valid cells represented as integers
S={D*r+c for r in range(R) for c in range(C) if a[r][c]}
# All valid regions rooted at each cell
s=[{x,*t} for x in S for t in combinations({x-D,x-1,x+1,x+D}&S,a[x//D][x%D]-1)]
# Start backtracking
return backtrack(a,s,S,D)
# a: array to fill in the region numbers
# s: current candidates of regions
# S: current remaining cells to cover
# D: constant from f
# d: recursion depth == group number in the result
def backtrack(a,s,S,D,d=1):
# Empty S: the board is correctly covered, return the result
if not S:return a
# Empty s: no more candidate regions to use, return false
if not s:return 0
h,*t=s
# h is not a subset of S: h is not a valid cover, try with the rest using same depth
if not h<=S:return backtrack(a,t,S,D,d)
# h is a valid cover, write d to the cells in h
for x in h:a[x//D][x%D]=d
return backtrack(a,t,S-h,D,d+1)or backtrack(a,t,S,D,d)
在线尝试!
注意:这是Set Packing的一种特殊情况,众所周知它是NP完整的。此特定问题的集合大小有限(最多4个),并且存在一种近似算法,可以在多项式时间内找到“良好的”集合装箱,但是它们不能保证最大可能的集合装箱(此问题对此是严格要求的)。
4
如果这些用例是有效的输入,则测试用例也应覆盖s。