给出一个3x3矩阵:
|1 2 3|
|4 5 6|
|7 8 9|
我想通过遵循以下规则连接此矩阵中的数字来计算所有组合:
一些示例:123、258、2589、123654等
例如1238不是很好的组合,因为3和8不相邻。 123和321组合不同。
希望我的描述清楚。
如果有人有任何想法,请告诉我。实际上,我不知道如何开始:D。谢谢
答案 0 :(得分:0)
这是一个搜索问题。您可以将简单的深度优先搜索与递归编程一起使用,以快速解决问题。类似于以下内容:
func search(matrix[N][M], x, y, digitsUsed[10], combination[L]) {
if length(combination) between 3 and 9 {
add this combination into your solution
}
// four adjacent directions to be attempted
dx = {1,0,0,-1}
dy = {0,1,-1,0}
for i = 0; i < 4; i++ {
next_x = x + dx[i]
next_y = y + dy[i]
if in_matrix(next_x, next_y) and not digitsUsed[matrix[next_x][next_y]] {
digitsUsed[matrix[next_x][next_y]] = true
combination += matrix[next_x][next_y]
search(matrix, next_x, next_y, digitsUsed, combination)
// At this time, sub-search starts with (next_x, next_y) has been completed.
digitsUsed[matrix[next_x][next_y]] = false
}
}
}
因此,您可以为矩阵中的每个网格运行搜索功能,并且解决方案中的每个组合都互不相同,因为它们是从不同的网格开始的。
此外,我们不需要记录表明矩阵中的一个网格已经遍历或未遍历的状态,因为每个数字只能使用一次,因此遍历过的网格将永远不会再遍历数字已经包含在组合中。
答案 1 :(得分:0)
这是Python 3中作为递归深度优先探索的一种可能实现:
def find_combinations(data, min_length, max_length):
# Matrix of booleans indicating what values have been used
visited = [[False for _ in row] for row in data]
# Current combination
comb = []
# Start recursive algorithm at every possible position
for i in range(len(data)):
for j in range(len(data[i])):
# Add initial combination element and mark as visited
comb.append(data[i][j])
visited[i][j] = True
# Start recursive algorithm
yield from find_combinations_rec(data, min_length, max_length, visited, comb, i, j)
# After all combinations with current element have been produced remove it
visited[i][j] = False
comb.pop()
def find_combinations_rec(data, min_length, max_length, visited, comb, i, j):
# Yield the current combination if it has the right size
if min_length <= len(comb) <= max_length:
yield comb.copy()
# Stop the recursion after reaching maximum length
if len(comb) >= max_length:
return
# For each neighbor of the last added element
for i2, j2 in ((i - 1, j), (i, j - 1), (i, j + 1), (i + 1, j)):
# Check the neighbor is valid and not visited
if i2 < 0 or i2 >= len(data) or j2 < 0 or j2 >= len(data[i2]) or visited[i2][j2]:
continue
# Add neighbor and mark as visited
comb.append(data[i2][j2])
visited[i2][j2] = True
# Produce combinations for current starting sequence
yield from find_combinations_rec(data, min_length, max_length, visited, comb, i2, j2)
# Remove last added combination element
visited[i2][j2] = False
comb.pop()
# Try it
data = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
min_length = 3
max_length = 9
for comb in find_combinations(data, min_length, max_length):
print(c)
输出:
[1, 2, 3]
[1, 2, 3, 6]
[1, 2, 3, 6, 5]
[1, 2, 3, 6, 5, 4]
[1, 2, 3, 6, 5, 4, 7]
[1, 2, 3, 6, 5, 4, 7, 8]
[1, 2, 3, 6, 5, 4, 7, 8, 9]
[1, 2, 3, 6, 5, 8]
[1, 2, 3, 6, 5, 8, 7]
[1, 2, 3, 6, 5, 8, 7, 4]
[1, 2, 3, 6, 5, 8, 9]
[1, 2, 3, 6, 9]
[1, 2, 3, 6, 9, 8]
[1, 2, 3, 6, 9, 8, 5]
[1, 2, 3, 6, 9, 8, 5, 4]
[1, 2, 3, 6, 9, 8, 5, 4, 7]
...
答案 2 :(得分:0)
查看所有组合,然后进行连接:
import itertools
def coords(n):
"""Coordinates of number n in the matrix."""
return (n - 1) // 3, (n - 1) % 3
def adjacent(a, b):
"""Check if a and b are adjacent in the matrix."""
ai, aj = coords(a)
bi, bj = coords(b)
return abs(ai - bi) + abs(aj - bj) == 1
def connected(comb):
"""Check if combination is connected."""
return all(adjacent(a, b) for a, b in zip(comb, comb[1:]))
for width in range(3, 10):
for comb in itertools.permutations(range(1, 10), width):
if connected(comb):
print(comb)