巴士路线:每条路线仅2个站点即可获得多条路线

时间:2019-07-15 11:54:50

标签: python algorithm optimization graph-algorithm

因此,我列出了公交车可以通过的路线以及每条路线的距离:

routes = {'AB':5, 'BC':4, 'CD':8, 'DC':8, 'DE':6, 'AD':5, 'CE':2, 'EB':3, 'AE':7}

或仅作为列表,因为距离尚不重要:

paths = ['AB', 'BC', 'CD', 'DC', 'DE', 'AD', 'CE', 'EB', 'AE']

现在,我正在尝试获取给定起点和终点的公交车可能采取的路线列表,然后我想尝试合并最大停靠点以限制数据输出。目前为止,我已经有了一个功能:

def route_variations(first_stop, last_stop, max_stops):
    possiblepaths = []

    for path in paths:
        x = path[0]     #first letter of each route
        if first_stop == x:
            possiblepaths.append(path)

    for path in paths:
        y = path[-1]    #last letter of each route
        if last_stop == y:
            possiblepaths.append(path)
    return possiblepaths

例如,如果我想以C开头和结尾

route_variations('C','C', 10)

将返回以C开头并以C结束的路由列表,即。 -> ['CD','CE','BC','DC']

所以现在我也需要连接路由。路线C-E-B-C需要输出中缺少的E-B路线。任何想法如何开始实施?然后加入他们以实现CDC之类的完整路线,而不是CD和DC?

2 个答案:

答案 0 :(得分:0)

图论中有众所周知的算法可以找到路径,正如对您的问题的评论所暗示的那样。

但是,仅出于学习目的(严重的是,仅出于学习目的,此代码实际上并不适合此任务的一般情况),我将尝试提供一个结构类似于您的简单示例代码,因此您可以查看获得这些“连接路线”所缺少的内容

基本原理是,当您找到正确的路径(通过比较第一个字母)时,您将查找此路径开头的所有路径,通过从自身内部(即递归)再次调用该函数,并找到第二个字母路径。

paths = ['AB', 'BC', 'CD', 'DC', 'DE', 'AD', 'CE', 'EB', 'AE']


def route_variations(first_stop, last_stop, max_stops):
    possible_routes = []
    if max_stops == 0 or first_stop == last_stop:
        return possible_routes
    for path in paths:
        x,y = path
        if first_stop == x:
            if last_stop == y:
                possible_routes.append([path])
            routes_from_this_stop = route_variations(y, last_stop, max_stops - 1)
            possible_routes.extend([[path] + route for route in routes_from_this_stop])
    return possible_routes


print(route_variations('A', 'C', 10))

输出为:

[['AB', 'BC'], ['AD', 'DC'], ['AD', 'DE', 'EB', 'BC'], ['AE', 'EB', 'BC']]

注意::如果路线中有圆圈,您会在圆圈中绕过许多类似的路线(长度受max_stops限制)。

注意2::当开始和停止相同时,这将不起作用,您将得到一个空结果,因此您的特定示例在这里无效:(

答案 1 :(得分:0)

我用itertools和置换解决了它。如果要在大量公交车站上运行它,它可能不是最快的方法,但是在8站以下的组合中,它运行起来相当快。

作为输出,您将获得具有简化路线和总距离的字典:

import itertools

paths = ['AB', 'BC', 'CD', 'DC', 'DE', 'AD', 'CE', 'EB', 'AE']
routes = {'AB':5, 'BC':4, 'CD':8, 'DC':8, 'DE':6, 'AD':5, 'CE':2, 'EB':3, 'AE':7}

def route_variations(first_stop, last_stop, max_length):
    valid_routes = []
    for n in list(range(2, max_length+1)):
        combinations = itertools.product(paths, repeat=n)
        for combination in combinations:
            print (combination)
            for i in list(range(n)):
                if i == 0:
                    if combination[i][0] != first_stop:
                        break
                elif i != 0 and i != n-1:
                    if combination[i][0] != combination[i-1][1]:
                        break
                elif i == n-1:
                    if combination[i][0] == combination[i-1][1] and combination[i][1] == last_stop:
                        valid_routes.append(combination)
                    else:
                        break
    result = {}
    for route in valid_routes:
        route_simple = ""
        dist = 0
        for j in route:
            dist += routes.get(j)
            if route.index(j) == 0:
                route_simple += str(j)
            else:
                route_simple += str(j[1])
        result[route_simple] = dist

    return result


print(route_variations('A', 'C', 6))