Python 网格中的回溯
假设有一个由1和0组成的二维网格,例如-Python 网格中的回溯,python,algorithm,backtracking,recursive-backtracking,Python,Algorithm,Backtracking,Recursive Backtracking,假设有一个由1和0组成的二维网格,例如- 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 网格被“折叠”以形成一个更小的网格,少行一列,因此上面的示例将被“折叠”以形成一个3行3列的网格 新值由以下规则确定: new_grid[i][j] is dependent on i) old_grid[i][j], ii) old_grid[i][j+1], iii) old_grid[i+1][j] iv) old_grid[i+1][j+1] If exactly
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
网格被“折叠”以形成一个更小的网格,少行一列,因此上面的示例将被“折叠”以形成一个3行3列的网格
新值由以下规则确定:
new_grid[i][j] is dependent on
i) old_grid[i][j],
ii) old_grid[i][j+1],
iii) old_grid[i+1][j]
iv) old_grid[i+1][j+1]
If exactly one of the above values are 1, then new_grid[i][j] will be 1, else 0.
因此,对于示例网格,在[0][0]、[0][1]、[1][0]和[1][1]
中,只有[0][1]
是1
,因此新网格中的[0][0]
将是1。同样,在[0][1]、[0][2]、[1][1]和[1][2]
中,[0][1]和[1][2]
都是1
,因此新网格中的[0][1]
将是0
输入以新网格
值的形式给出。我必须找出旧网格
的可能配置数量,以便通过提供的折叠规则可以实现新网格
我的方法
我目前想到的回溯解决方案是这样的-
为旧网格中的每个1值单元格标识虚拟2X2框,该框将对应于新网格中的相应单元格
所有这些框将只包含一个值为1的单元格,因此在每个框的随机单元格中放入1
递归检查在随机单元格中放置1是否确保每个框仍保留一个值为1的单元格
如果最终获得网格配置,其中每个框正好包含一个值为1的单元格,请检查配置是否可以“折叠”以获得新网格
如果不是,则使用值为1的其他单元格重复此过程
如果在旧网格中有一些细胞不在任何“盒子”下,那么它们就是我称之为“无关紧要”的细胞
比如说-
1 1
0 0
对于上述新网格
,旧网格
可以-
1 0 1
0 0 0
0 0 0
或
最后一行的单元格是“无关紧要”的单元格,因为它们不在任何2X2框下,它们都可以是1
s或0
s作为有效配置(我认为这是我们可以灵活操作它们的程度,尽管我不确定)
我的问题是-这个算法很可能是指数增长的,对于一个网格,比如说,50X10
,它需要很多时间
还有别的办法解决这个问题吗?或者有没有什么聪明的算法可以不经过所有可能的配置来计算它们呢?Hmm,所以我想到了一个2x3的新网格,如下所示:
newGrid: 0 1 0
0 0 0
需要由这些3x4旧网格中的任何一个生成:
每个
可以是1
或0
oldGrid 1: _ 0 1 _
_ 0 0 _
_ _ _ _
oldGrid 2: _ 1 0 _
_ 0 0 _
_ _ _ _
oldGrid 3: _ 0 0 _
_ 1 0 _
_ _ _ _
oldGrid 4: _ 0 0 _
_ 0 1 _
_ _ _ _
剩下的8个点都可以用2^8种方式填充。
所以答案是4*2^8
但是,想象一下,如果newGrid有多个1:
newGrid: 1 1 0
0 0 0
其中将包含以下8个旧网格:
oldGrid 1: 1 0 _ _
0 0 _ _
_ _ _ _
oldGrid 2: 0 1 _ _
0 0 _ _
_ _ _ _
oldGrid 3: 0 0 _ _
1 0 _ _
_ _ _ _
oldGrid 4: 0 0 _ _
0 1 _ _
_ _ _ _
oldGrid 5: _ 1 0 _
_ 0 0 _
_ _ _ _
oldGrid 6: _ 0 1 _
_ 0 0 _
_ _ _ _
oldGrid 7: _ 0 0 _
_ 1 0 _
_ _ _ _
oldGrid 8: _ 0 0 _
_ 0 1 _
_ _ _ _
从oldGrid 1
中,我将生成2^8个组合。但请注意,其中一些解决方案将与oldGrid 6
产生的解决方案相同。是那些看起来像这样的:
oldGrid 1.1: 1 0 1 _
0 0 0 _
_ _ _ _
它有2^6个解决方案
因此,oldGrid 1
有2^8-2^6个解决方案,与oldGrid 6
不冲突
而oldGrid 6
有2^6个解决方案与oldGrid 1
不冲突
他们有(2^8-2^6)+(2^8-2^6)+2^6个解决方案
1和6,1和8,2和5,3和6,3和8,4和7有冲突的解空间,每个解空间都有2^6
我认为这意味着解决方案的数量是8*2^8-6*2^6。
也就是说:
numberOfSolutions = numberOf1s * 4 * 2^(oldGridSize-4) - overlappingSolutionsCount
overlappingSolutionsCount = numberOfOverlappingPairs * 2^(oldGridSize-4-overlapAreaSize)
如何计算重叠
最后的算法是:
我无法努力编写python代码,但我希望解决方案是正确的,并且/或者显示出一种方法您应该研究极小极大中的常量编程和alpha-beta修剪。您可能还想考虑添加[algorithm]标记。这与我在一月份发布的内容完全相同。如果你仍然需要答案,这里有两个问题。问题中输入矩阵的最大大小是多少?此外,我们需要计算所有可能的旧矩阵还是只打印一个有效答案?@A.Mashreghi-最大大小为50X10
,我需要计算所有可能的答案。
numberOfSolutions = numberOf1s * 4 * 2^(oldGridSize-4) - overlappingSolutionsCount
overlappingSolutionsCount = numberOfOverlappingPairs * 2^(oldGridSize-4-overlapAreaSize)
function countOverlappingSolutions(newGrid: an MxN matrix) {
result = 0
oldGridSize = (M+1) * (N+1)
for each pair of 1s in the newGrid:
let manhattanDistance = manhattan distance between the 1s in the pair
let overlapAreaSize = 0
if the 1s are in the same row or column
if manhattanDistance == 1:
overlapSize = 2
else if manhattanDistance == 2
overlapAreaSize = 1
result += 2^(oldGridSize -4 -overlapAreaSize)
return result
}
let newGrid be a MxN matrix
let numberOf1s = number of 1s in newGrid
let oldGridSize = (M+1) * (N+1)
result = numberOf1s * 4 * 2^(oldGridSize - 4) - countOverlappingSolutions(newGrid)