构建电路通过起始框在矩阵中水平和垂直搜索其他非空框

1 投票
1 回答
82 浏览
提问于 2025-04-14 17:57
from random import shuffle


matrix_aux_with_num_decompositions = [
    [None,  'b', None,  100,  100,   -3],
    [None, None,  200,  'a', None,  100],
    [ 100,  200, None, None, None, None],
]

matrix_aux_with_num_decompositions_aux = [
    [     -1, 'asign',      -3, 'asign', 'asign',      -3],
    [      5,       4, 'asign', 'asign',      -2, 'asign'],
    ['asign', 'asign',      -9,      -3,      -1,      -5],
]

#Possible coordinates of lockers that will function as starting points for the possible circuit
#Note that they are the coordinates of the only positive values within the matrix called matrix_aux_with_num_decompositions_aux
coords_posibles_elementos_de_partida = [ [1, 0], [1, 1] ]
#optionally we can exchange the starting points to analyze them randomly
shuffle(coords_posibles_elementos_de_partida)

我需要尝试列表 coords_posibles_elementos_de_partida 中每一个坐标(格式为 [行, 列]),直到找到一个可以构建闭合电路的坐标。这个电路必须遵循只能水平和垂直提取数据的规则,并且必须在起点结束,也就是说,最后要回到从 coords_posibles_elementos_de_partida 中选择的坐标。

其余的坐标我们称之为 顶点,这些顶点的值必须不同于 None,并且要在矩阵 matrix_aux_with_num_decompositions 的范围内。

电路 不能有对角线连接,并且必须是闭合的。例如,如果电路从 [1, 0] 开始,它必须在 matrix_aux_with_num_decompositions 中循环经过不同于 None 的值,并将这些值作为顶点。

输出列表的表达方式应该是:

[[起点行, 起点列], [第一个顶点行, 第一个顶点列], ..., [第i个顶点行, 第i个顶点列]]

这个列表会是一个可能的正确列表(正确的输出),其中顶点按顺序列出,从起点开始(并且要闭合,因为它要回到起点)。

circuit_list = [[1, 0], [1, 3], [0, 3], [0, 1], [2, 1], [2,0] ]

在最后一个顶点之后,比如 [2, 0],电路会返回到起点 [1, 0],因为电路是闭合的。

这是我的代码,但它的逻辑并没有正确工作。

def is_valid_move(matrix, visited, row, col):
    # Check if the move is within the matrix boundaries and the cell is not visited
    return 0 <= row < len(matrix) and 0 <= col < len(matrix[0]) and not visited[row][col] and matrix[row][col] is not None

#Depth-First Search is a graph traversal algorithm used to explore nodes and edges of a graph
def dfs(matrix, visited, row, col, start_row, start_col, path):
    # Define the possible moves: up, down, left, right
    moves = [(-1, 0), (1, 0), (0, -1), (0, 1)]

    # Mark the current cell as visited
    visited[row][col] = True

    # Append the current cell to the path
    path.append([row, col])

    # If the current cell is the starting cell and all cells are visited, return the path
    if row == start_row and col == start_col and all(all(cell for cell in row) for row in visited):
        return path

    # Explore all possible moves
    for move in moves:
        new_row, new_col = row + move[0], col + move[1]
        if is_valid_move(matrix, visited, new_row, new_col):
            result = dfs(matrix, visited, new_row, new_col, start_row, start_col, path)
            if result:
                return result

    # If no valid moves left, backtrack
    visited[row][col] = False
    path.pop()
    return None
def find_circuit(matrix, start_coords):
    for start_coord in start_coords:
        start_row, start_col = start_coord
        visited = [[False for _ in range(len(matrix[0]))] for _ in range(len(matrix))]
        path = []

        circuit = dfs(matrix, visited, start_row, start_col, start_row, start_col, path)

        if circuit:
            return circuit

    return None
# Find a possible closed loop
circuit = find_circuit(matrix_aux_with_num_decompositions, coords_posibles_elementos_de_partida)

# Print Circuit Vertex List
if circuit:
    print("Circuit found: ")
    print(circuit)
else:
    print("No closed circuit found.")

但是不幸的是,我的代码出错了,它错误地表示没有可能的电路,但这并不正确,因为在下面的图片中,我们可以看到至少可以画出一个电路。

这里是图片

这里有一张关于可能和不可能电路的示例图片:

可能和不可能的电路

1 个回答

1

一般来说,自己去做这个并不划算;可以直接使用NetworkX:

import networkx
from matplotlib import pyplot as plt

matrix = [
    [None,  'b', None,  100,  100,   -3],
    [None, None,  200,  'a', None,  100],
    [ 100,  200, None, None, None, None],
]
m = len(matrix)
n = len(matrix[0])

graph = networkx.Graph()

for i, row in enumerate(matrix):
    graph.update(
        networkx.complete_graph([
            (i, j)
            for j, elm in enumerate(row)
            if elm is not None
        ])
    )
for j in range(n):
    graph.update(
        networkx.complete_graph([
            (i, j)
            for i, row in enumerate(matrix)
            if row[j] is not None
        ])
    )

print(networkx.find_cycle(graph))

networkx.draw(graph, with_labels=True)
plt.show()
[((0, 1), (0, 3)), ((0, 3), (0, 4)), ((0, 4), (0, 1))]

graph graph

根据你那条(还不是很明确的)“不能有直线”的规则,你可以从所有可能的循环中选择:

for cycle in networkx.simple_cycles(graph):
    if len({
        i for i, j in cycle
    }) > 1 and len({
        j for i, j in cycle
    }) > 1:
        print(cycle)
[(0, 1), (0, 3), (1, 3), (1, 2), (1, 5), (0, 5)]
[(0, 1), (0, 3), (1, 3), (1, 2), (1, 5), (0, 5), (0, 4)]
[(0, 1), (0, 3), (1, 3), (1, 5), (0, 5)]
[(0, 1), (0, 3), (1, 3), (1, 5), (0, 5), (0, 4)]
[(0, 1), (0, 4), (0, 3), (1, 3), (1, 2), (1, 5), (0, 5)]
[(0, 1), (0, 4), (0, 3), (1, 3), (1, 5), (0, 5)]
[(0, 3), (0, 4), (0, 5), (1, 5), (1, 2), (1, 3)]
[(0, 3), (0, 4), (0, 5), (1, 5), (1, 3)]
[(0, 3), (0, 5), (1, 5), (1, 2), (1, 3)]
[(0, 3), (0, 5), (1, 5), (1, 3)]

撰写回答