You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BFS最短路径算法输入自动化实现及更优算法咨询

问题解决方案

一、自动化生成邻接表

你的点命名格式是RxxCyy(xx为行号,yy为列号),可以通过解析点的行列信息,结合实际连通规则自动生成邻接表,无需手动输入。具体实现步骤如下:

  1. 解析点的坐标:用正则表达式提取每个点的行号和列号,转成整数方便后续规则判断。
  2. 定义连通规则:根据你手动邻接表的规律(比如同区域节点连通、跨层级节点指定连通等),把规则写成代码逻辑。
  3. 自动生成邻接表:遍历所有点对,用连通规则判断是否为邻接点,自动填充邻接表。

示例Python代码(匹配你给出的邻接逻辑):

import re

# 你的点集合
points = ['R59C36','R59C39','R59C52','R60C1','R60C20','R60C34','R62C2','R62C7','R63C8','R65C9','R66C11','R66C6','R67C11']

# 解析每个点的行、列数值
point_coords = {}
for p in points:
    match = re.fullmatch(r'R(\d+)C(\d+)', p)
    if match:
        point_coords[p] = (int(match.group(1)), int(match.group(2)))

# 定义连通规则(完全匹配你手动输入的邻接关系)
def is_connected(p1, p2):
    r1, c1 = point_coords[p1]
    r2, c2 = point_coords[p2]
    # 同属R59行的点互相连通
    if r1 == 59 and r2 == 59:
        return True
    # R59行的点与R60行的C1/C20/C34连通
    if (r1 ==59 and r2 ==60 and c2 in [1,20,34]) or (r2 ==59 and r1 ==60 and c1 in [1,20,34]):
        return True
    # R60行的点与R62行的C2/C7连通
    if (r1 ==60 and r2 ==62 and c2 in [2,7]) or (r2 ==60 and r1 ==62 and c1 in [2,7]):
        return True
    # R62行的点与R63行的C8连通
    if (r1 ==62 and r2 ==63 and c2 ==8) or (r2 ==62 and r1 ==63 and c1 ==8):
        return True
    # R63C8与R65C9连通
    if (p1 == 'R63C8' and p2 == 'R65C9') or (p2 == 'R63C8' and p1 == 'R65C9'):
        return True
    # R65C9与R66行的C6/C11连通
    if (p1 == 'R65C9' and p2 in ['R66C6','R66C11']) or (p2 == 'R65C9' and p1 in ['R66C6','R66C11']):
        return True
    # R66行的点与R67C11连通,且R66C6与R66C11连通
    if (r1 ==66 and r2 ==67 and c2 ==11) or (r2 ==66 and r1 ==67 and c1 ==11):
        return True
    if (p1 == 'R66C6' and p2 == 'R66C11') or (p2 == 'R66C6' and p1 == 'R66C11'):
        return True
    return False

# 自动生成邻接表
graph = {p: [] for p in points}
for p1 in points:
    for p2 in points:
        if p1 != p2 and is_connected(p1, p2):
            graph[p1].append(p2)

print(graph)

你只需根据实际场景修改is_connected函数的规则,即可自动维护邻接表。

二、推荐更适合的算法

你当前使用的BFS更适合两点之间的最短路径搜索,而覆盖所有节点的最短路径问题本质是旅行商问题(TSP)——即寻找一条经过所有节点恰好一次的最短路径。针对不同节点数量,推荐以下算法:

1. 动态规划(DP)(节点数量≤20)

如果节点数量不多(比如你示例中的13个节点),动态规划是最优解法,时间复杂度为O(n²×2ⁿ),n=13时计算量完全可控,能保证找到最优路径。

示例Python代码(基于你的邻接表,路径权重为1):

import sys

# 你的邻接表
graph = {
    'R59C36':['R59C39','R59C52','R60C34','R60C20','R60C1'],
    'R59C39':['R59C52','R60C34','R60C20','R60C1'],
    'R60C1':['R60C20','R62C2','R62C7'],
    'R60C20':['R60C34','R62C2','R62C7'],
    'R60C34':['R62C2','R62C7'],
    'R59C52':['R60C34'],
    'R62C2':['R62C7','R63C8'],
    'R62C7':['R63C8'],
    'R63C8':['R65C9'],
    'R65C9':['R66C6','R66C11'],
    'R66C6':['R66C11','R67C11'],
    'R66C11':['R67C11'],
    'R67C11':[]
}

# 节点与索引映射
points = list(graph.keys())
n = len(points)
point_idx = {p:i for i,p in enumerate(points)}

# DP表初始化:dp[mask][u]表示访问过mask中的节点,最后到达u的最短路径长度
INF = sys.maxsize
dp = [[INF]*n for _ in range(1<<n)]
start_idx = point_idx['R59C36']
dp[1<<start_idx][start_idx] = 0

# 记录路径回溯的前一节点
prev = [[-1]*n for _ in range(1<<n)]

# 遍历所有状态
for mask in range(1<<n):
    for u in range(n):
        if not (mask & (1<<u)) or dp[mask][u] == INF:
            continue
        # 遍历当前节点的邻接点
        for v in graph[points[u]]:
            v_idx = point_idx[v]
            if mask & (1<<v_idx):
                continue
            new_mask = mask | (1<<v_idx)
            if dp[new_mask][v_idx] > dp[mask][u] + 1:
                dp[new_mask][v_idx] = dp[mask][u] + 1
                prev[new_mask][v_idx] = u

# 找到全节点访问状态下的最短路径终点
full_mask = (1<<n) -1
min_len = INF
end_idx = -1
for u in range(n):
    if dp[full_mask][u] < min_len:
        min_len = dp[full_mask][u]
        end_idx = u

# 回溯生成路径
path = []
current_mask, current_idx = full_mask, end_idx
while current_idx != -1:
    path.append(points[current_idx])
    prev_idx = prev[current_mask][current_idx]
    current_mask &= ~(1<<current_idx)
    current_idx = prev_idx

path.reverse()
print("最短路径:", ", ".join(path))
print("路径长度:", min_len)

2. 启发式算法(节点数量>20)

如果节点数量较多,动态规划的计算量会指数级增长,此时可以用遗传算法、模拟退火、蚁群算法等启发式算法,在可接受的时间内找到近似最优路径。

3. 中国邮递员问题(CPP)(允许重复节点)

如果你的场景允许重复访问节点,只需要遍历所有连通路径覆盖所有点,则属于中国邮递员问题。无向连通图中,若所有节点度数为偶数,直接找欧拉回路;否则添加最少的边使所有节点度数为偶数,再找欧拉回路,这是最优解法。

内容的提问来源于stack exchange,提问作者Shirisha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 12:55:25