n个节点的完全图,每两个节点之间,路经m条线的最短距离。光明小学接力赛最短路径问题。

光明小学的小朋友们要举行一年一度的接力跑大赛了,但是小朋友们却遇到了一个难题:设计接力跑大赛的线路,你能帮助他们完成这项工作么?
光明小学可以抽象成一张有N个节点的图,每两点间都有一条道路相连。光明小学的每个班都有M个学生,所以你要为他们设计出一条恰好经过M条边的路径。
光明小学的小朋友们希望全盘考虑所有的因素,所以你需要把任意两点间经过M条边的最短路径的距离输出出来以供参考。
你需要设计这样一个函数:
res[][] Solve( N, M, map[][]);
注意:map必然是N * N的二维数组,且map[i][j] == map[j][i],map[i][i] == 0,-1e8 <= map[i][j] <= 1e8。(道路全部是无向边,无自环)2 <= N <= 100, 2 <= M <= 1e6。要求时间复杂度控制在O(N^3*log(M))。
map数组表示了一张稠密图,其中任意两个不同节点i,j间都有一条边,边的长度为map[i][j]。N表示其中的节点数。
你要返回的数组也必然是一个N * N的二维数组,表示从i出发走到j,经过M条边的最短路径
你的路径中应考虑包含重复边的情况。
样例:
N = 3
M = 2
map = {
{0, 2, 3},
{2, 0, 1},
{3, 1, 0}
}

输出结果result为:
result = {
{4, 4, 3},
{4, 2, 5},
{3, 5, 2}
}
样例解释:
1->1有两种方法:1->2->1(长度为2+2=4),1->3->1(长度为3+3=6)
2->2有两种方法:2->1->2(长度为2+2=4),2->3->2(长度为1+1=2)
3->3有两种方法:3->1->3(长度为3+3=6),3->2->3(长度为1+1=2)
1->2只有一个方法:1->3->2(长度为3+1=4)
1->3只有一个方法:1->2->3(长度为2+1=3)
2->3只有一个方法:2->1->3(长度为2+3=5)
根据对称性可以得到其它部分的答案

编译器版本: Python 2.7.6
请使用标准输出(sys.stdout);已禁用图形、文件、网络、系统相关的操作,如Process , httplib , os;缩进可以使用tab、4个空格或2个空格,但是只能任选其中一种,不能多种混用;如果使用sys.stdin.readline,因为默认会带换行符,所以要strip(' ')进行截取;建议使用raw_input()
时间限制: 3S (C/C++以外的语言为: 5 S)   内存限制: 128M (C/C++以外的语言为: 640 M)
输入:
输入范例 例如下面表示总共3个节点和:
3    (表示N=3)
2    (M=2)
下面是N*N的矩阵(此处是一个3*3的矩阵)
3 3
0 2 3
2 0 1
3 1 0
输出:
输出是一个N*N的矩阵(此处根据输入得到是一个3*3的矩阵)
4 4 3
4 2 5
3 5 2
输入范例:
3
2
3 3
0 2 3
2 0 1
3 1 0
输出范例:
4 4 3
4 2 5
3 5 2

# 分析:
# 首先,假设从 i 到 j 经过(m-1)条边的最短距离已知,存储在last_opt[n][n]二维数组中。那么从 i 到 j 经过m条边的最短距离简化成:
# dp_opt=min(last_opt [i] [x] + map [x] [j] )
# 经过m条边的最短路径只和最后一步的路径以及走(m-1)步的最短路径有关,
# map [x] [j] 表示最后一步,# last_opt [i] [x] 表示从起点 i 走m-1 步到x的最短路径。
# 附上Python 2代码,时间复杂度 O(n^3*(m-1)),空间复杂度O(2*n^2)

def minPath(n,m,map):
    last_opt=[x[:] for x in map]#初始化,前一步的最短路径
    print last_opt
    dp_opt=[x[:] for x in map]#初始化,临时的每一步的最短路径
    print dp_opt
    for step in range(m-1):#只需要循环 m-1次
        for i in range(n):
            for j in range(n):
                temp = [last_opt[i][x] + map[x][j] for x in range(n) if map[x][j]!=0 and last_opt[i][x]!=0] #递推式转换 注意判断条件
                print 'step',step,'i',i,'j',j,'temp',temp,'min_temp',min(temp)
                dp_opt[i][j] = min(temp)#取所有情况中的最小值
                for k in dp_opt:
                    print k
        last_opt=[x[:] for x in dp_opt]#拷贝以待下次循环
    print 'dp_opt',  dp_opt
    print 'last_opt',last_opt
    return dp_opt#或者last_opt也行
if __name__ == '__main__':
    n = int(input())
    m = int(input())
    x=raw_input()
    map = []
    for i in range(n):
        map.append([int(x) for x in raw_input().split()])
    res=minPath(n,m,map)
    for x in res:
        print x

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值