Python 具有挑战性的动态规划问题
这是一个我需要解决的计算机视觉问题的缓和版本。假设给定了参数n,q,并且必须计算将整数0..(q-1)赋值给n×n网格元素的方法的数量,以便对于每个赋值,以下都是真的Python 具有挑战性的动态规划问题,python,complexity-theory,dynamic-programming,Python,Complexity Theory,Dynamic Programming,这是一个我需要解决的计算机视觉问题的缓和版本。假设给定了参数n,q,并且必须计算将整数0..(q-1)赋值给n×n网格元素的方法的数量,以便对于每个赋值,以下都是真的 没有两个邻居(水平或垂直)获得相同的值 位置(i,j)处的值为0 位置(k,l)处的值为0 因为没有给出(i,j,k,l),所以输出应该是上面的一组求值,对于(i,j,k,l)的每个有效设置一个求值 下面是一种暴力手段。我们的目标是得到一个适用于q0 else-1的高效算法 右=网格[r][c-1],如果c 0,则为-1 底部=网
我也在TopCoder上问过这个问题,他们的解决方案是我迄今为止看到的最有效的解决方案(根据作者的估计,对于n=10,任意q,大约3个小时)这不是一个答案,只是对讨论的贡献,讨论太长,无法发表评论 tl;博士任何归结为“计算可能性并计算它们”的算法,如Eric Lippert的算法或蛮力方法,都无法实现@Yaroslav的
q=4
目标。从芥末柱的顶部单元格开始。我们只需要担心bread列的相邻单元格,它们最多有2个唯一值。为芥末色列选择第三个数字。考虑芥菜柱的第二个细胞。我们必须考虑以前的芥菜细胞和2个相邻的面包细胞,总共有最多3个独特的值。选择第四个值。继续填写芥末栏
我们最多有2列包含硬编码单元格0。因此,使用芥末柱,我们可以制作至少6个面包柱,每个面包柱大约有10^36
个解,总共至少有10^216
个有效解,给或取一个数量级的舍入误差
根据维基百科,宇宙中大约有10^80个原子
因此,要更聪明。也许这听起来太简单了,但它确实有效。将值随机分布到所有单元格,直到只有两个单元格为空。测试所有值的邻接性。计算成功转换与所有转换的平均百分比,直到差异降至可接受的范围内
风险为零,处于风险中的只是一点运行时间。我正在根据Dave Aaron Smith对讨论的贡献构建一个贡献
现在不要考虑最后两个约束(<代码>(i,j)< /代码>和<代码>(k,l)< /代码>)。
只有一列(nx1)的解决方案是q*(q-1)^(n-1)
第二列有多少个选项<代码>(q-1)用于顶部单元格(1,2),但如果(1,2)/(2,1)具有或不具有相同的颜色,则该单元格(2,2)的
q-1
或q-2
(3,2)也是一样:q-1
或q-2
解决方案
我们可以看到,我们有一个可能性的二叉树,我们需要在这棵树上求和。让我们假设左边的子对象总是“顶部和左侧的颜色相同”,右边的子对象是“不同的颜色”
通过在树上计算左列创建这种配置的可能性数量,以及我们正在着色的新单元的可能性数量,我们将计算两列着色的可能性数量
但是现在让我们考虑第二列着色的概率分布:如果我们想迭代这个过程,我们需要在第二列上有均匀的分布,这就像第一个颜色不存在一样,在前两列的所有颜色中,我们可以说
1/q
其中的第二列的顶部单元格中有颜色0
没有统一的分布,这是不可能的
问题是:分布是否均匀
回答:
通过构建第一列、第二列、第一列和第三列,我们可以得到相同数量的解。在这种情况下,第二列的分布是均匀的,因此在第一种情况下也是如此
我们现在可以应用相同的“树思想”来计算第三列的可能性数量
我将尝试在此基础上发展并建立一个通用公式(因为树的大小为2^n,我们不想明确探讨它)。一些观察结果也可能有助于其他回答者:
def tuples(n,q):
return [[a,]+b for a in range(q) for b in tuples(n-1,q)] if n>1 else [[a] for a in range(q)]
def isvalid(t,n):
grid=[t[n*i:n*(i+1)] for i in range(n)];
for r in range(n):
for c in range(n):
v=grid[r][c]
left=grid[r][c-1] if c>0 else -1
right=grid[r][c-1] if c<n-1 else -1
top=grid[r-1][c] if r > 0 else -1
bottom=grid[r+1][c] if r < n-1 else -1
if v==left or v==right or v==top or v==bottom:
return False
return True
def count(n,q):
result=[]
for pos1 in range(n**2):
for pos2 in range(n**2):
total=0
for t in tuples(n**2,q):
if t[pos1]==0 and t[pos2]==0 and isvalid(t,n):
total+=1
result.append(total)
return result
assert count(2,2)==[1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1]