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

Python实现二维点最短路径 修复自定义算法路径点重复问题

自定义路径查找问题排查与修复

给定数据集

import math
import itertools

names = ['a', 'b', 'c', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
x = [3, 6, 6, 10, 12, 15, 3, 6, 13, 9, 13, 12]
y = [9, 12, 9, 9, 12, 9, 6, 3, 8, 3, 1, 3]

算法规则

需要实现的自定义路径规则如下,起点固定为a:

  • 每到一个当前点,先筛选出距离当前点最近的3个未访问点
  • 计算两种遍历顺序的累计路径长度:例如最近3点为b、c、d时,分别计算路径1:当前点→b→c→d、路径2:当前点→c→b→d的总距离
  • 比较两个总距离,路径2更短则选c作为下一跳,否则选b作为下一跳
  • 移动到选中的下一跳,重复上述流程直到所有点遍历完成

原有代码问题

原有代码接近实现目标,但存在几个核心逻辑错误导致重复点问题:

  • 已访问过滤逻辑失效:代码中预留的backup_list移除已访问点的逻辑被注释,筛选最近点时完全没有排除已经走过的点,直接导致重复点被加入路径
  • 累计距离计算逻辑错误:计算两条对比路径长度时,跳点匹配条件写错,没有正确匹配两点间的预计算距离,得到的对比值完全不准确
  • 循环终止条件错误:终止判断依赖的backup_list从未更新长度,判断阈值len(backup_list)-3不符合遍历所有点的终止要求
  • 点匹配歧义:原始names列表存在重复值b,直接用name做键匹配点会出现索引混淆,导致距离匹配错误

原有问题代码

def distance(p1, p2):
    return math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)


def get_hops():
    hopes = []
    for i in range(len(x)):
        for j in range(len(y)):
            dist = distance((x[i], y[i]), (x[j], y[j]))
            hopes.append({'from': names[i], 'to': names[j], 'dist': dist})
    return hopes


def get_points(points):
    point_1 = points[0]
    point_2 = points[0]
    point_3 = points[0]
    for point in points:
        if point['dist'] < point_1['dist']:
            point_1 = point

        if point['dist'] < point_2['dist'] and point['to'] != point_1['to']:
            point_2 = point

        if point['dist'] < point_3['dist'] and point['to'] != point_1['to'] and point['to'] != point_2['to']:
            point_3 = point

    return point_1, point_2, point_3


def get_optimal_path(names_list):
    backup_list = []
    for elm in names_list:
        backup_list.append(elm)
    points_list = [names_list[0]]
    backup_list.remove(names_list[0])
    hops = get_hops()
    for elm in itertools.cycle(names_list):
        if len(points_list) != len(backup_list)-3:
            print(elm, points_list[-1])
            if elm == points_list[-1]:

                # get closet 3 points to the last point in path
                hop_1 = {'from': 'qdsofhvcl', 'to': 'qjf', 'dist': 10000000000000}
                hop_2 = {'from': 'qdsofhvcl', 'to': 'qjf', 'dist': 10000000000000}
                hop_3 = {'from': 'qdsofhvcl', 'to': 'qjf', 'dist': 10000000000000}
                for hop in hops:
                    if hop['from'] == elm and hop['to'] != elm and hop['dist'] < hop_1['dist']:
                        hop_1 = hop

                for hop in hops:
                    if hop['from'] == elm and hop['to'] != elm and hop['dist'] < hop_2['dist'] and hop['to'] != hop_1['to']:
                        hop_2 = hop

                for hop in hops:
                    if hop['from'] == elm and hop['to'] != elm and hop['dist'] < hop_3['dist'] and hop['to'] != hop_1['to'] and hop['to'] != hop_2['to']:
                        hop_3 = hop

                # calculate dist_1 and dist_2 to determine optimal hoping point
                dist_1 = 0
                dist_2 = 0
                for hop in hops:
                    if hop['from'] == elm and hop['to'] == hop_1['to']:
                        dist_1 += hop['dist']
                    if hop_1['from'] == hop['from'] and hop_2['to'] == hop['to']:
                        dist_1 += hop['dist']
                    if hop_2['to'] == hop['from'] and hop['to'] == hop_3['to']:
                        dist_1 += hop['dist']

                    if hop['from'] == elm and hop['to'] == hop_2['to']:
                        dist_2 += hop['dist']
                    if hop_2['to'] == hop['from'] and hop_1['to'] == hop['to']:
                        dist_2 += hop['dist']
                    if hop_1['to'] == hop['from'] and hop['to'] == hop_3['to']:
                        dist_2 += hop['dist']

                # compare 2 distances and determine the best hoping point
                if dist_1 < dist_2:
                    points_list.append(hop_1['to'])
                    print(backup_list)
                    # backup_list.remove(hop_1['to'])
                else:
                    points_list.append(hop_2['to'])
                    print(backup_list)
                    # backup_list.remove(hop_2['to'])
        else:
            print('exit')
            break
        print(points_list)

修复后实现(保留原算法逻辑)

修复点对应上述问题,保留原算法的选点、比距逻辑,改用索引做唯一匹配避免重名问题:

def distance(p1, p2):
    return math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)

# 预计算所有点对之间的距离,用索引做唯一键避免重名问题
dist_matrix = [[0]*len(names) for _ in range(len(names))]
for i in range(len(names)):
    for j in range(len(names)):
        dist_matrix[i][j] = distance((x[i], y[i]), (x[j], y[j]))

def get_optimal_path(start_idx=0):
    visited = [False]*len(names)
    path = [start_idx]
    visited[start_idx] = True
    total_dist = 0

    while len(path) < len(names):
        current = path[-1]
        # 筛选所有未访问点,按距离从小到大排序
        unvisited = [(dist_matrix[current][j], j) for j in range(len(names)) if not visited[j]]
        unvisited.sort()
        # 剩余点不足3个时直接补全路径
        if len(unvisited) <=3:
            for _, idx in unvisited:
                path.append(idx)
                total_dist += dist_matrix[current][idx]
                current = idx
                visited[idx] = True
            break
        # 取最近的3个未访问点
        _, p1 = unvisited[0]
        _, p2 = unvisited[1]
        _, p3 = unvisited[2]
        # 计算两种顺序的累计距离
        dist1 = dist_matrix[current][p1] + dist_matrix[p1][p2] + dist_matrix[p2][p3]
        dist2 = dist_matrix[current][p2] + dist_matrix[p2][p1] + dist_matrix[p1][p3]
        # 选更优的下一跳
        next_p = p1 if dist1 < dist2 else p2
        path.append(next_p)
        total_dist += dist_matrix[current][next_p]
        visited[next_p] = True
    # 转换为name输出,重名点加索引区分
    path_name = [f"{names[i]}(idx:{i})" if names.count(names[i])>1 else names[i] for i in path]
    return path_name, total_dist

# 运行测试
path, total = get_optimal_path()
print("最终路径:", path)
print("总路径长度:", round(total,2))

运行后输出无重复点,完全符合预设算法规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:27:29