CCF-201712-4-行车路线

这题考最短路径,最短路径的变种
套用dijkstra模板,要改变的是 更新costs那里的判断。

重点:算到达某个结点的疲劳值
用一个数组(sum_small)存对应下标结点之前经过的连续小路之和
再用一个数组(sum_big)存对应下标结点之前的大路疲劳值之和

  1. 如果到达一个结点经过的是大路,只要在父结点的cost基础上加这条边的疲劳值就得到这条路径的cost。 cost = costs[minNode] + weight。小于之前的cost就更新,顺便也把该结点的sum_small归零。该结点的sum_big 被赋值为该路径疲劳。
  2. 如果到达一个结点经过的是小路,cost = (连续小路路程加该小路路程)的乘方 + 之前的大路疲劳。小于之前的cost就更新,顺便该结点的sum_small更新为连续小路路程加该小路程。该结点sum_big被赋值为父结点的sum_big。

注意:更新sum_big和sum_small的时候要确定cost小于原来的cost才更新。

有点抽象。。。怎么说呢,经过大路的时候算cost好算,但是经过小路就难算,所以才引进两个数组sum_small和sum_big,来存储路径前面的信息。这两个数组就是用来算小路的。经过小路的时候可以把路径分为两部分,(从路径开始到最后一个大路,最后一个大路后面的连续小路)sum_big用来存前者,sum_small用来存后者。

这个得现场画图才好说[笑哭]

python代码(100)

def dij(start, graph):
    n = len(graph)
    costs = [999999999 for _ in range(n)]
    costs[start] = 0
    sum_small = [0 for _ in range(n)]  # 到每个结点的小路的累计长度
    sum_big = [0 for _ in range(n)]  # 到每个结点的大路的累计长度
    visited = [False for _ in range(n)]
    t = []

    while len(t) < n:
        minNode = None
        minCost = 999999999
        for i in range(n):
            if not visited[i] and costs[i] < minCost:
                minCost = costs[i]
                minNode = i
        t += [minNode]
        visited[minNode] = True
        
        # 更新costs
        for toNode, weight, type in graph[minNode]:
            if not visited[toNode]:
                cost = 0  # 该路径花销
                if type == 0:
                    cost = costs[minNode] + weight
                    if cost < costs[toNode]:
                        costs[toNode] = cost
                        sum_small[toNode] = 0
                        sum_big[toNode] = cost
                elif type == 1:
                    cost = (sum_small[minNode] + weight) ** 2 + sum_big[minNode]
                    if cost < costs[toNode]:
                        costs[toNode] = cost
                        sum_small[toNode] = sum_small[minNode] + weight
                        sum_big[toNode] = sum_big[minNode]

    return costs


n, m = map(int, input().split())
graph = [[] for _ in range(n)]

for i in range(m):
    # t: 0大, 1小
    t, a, b, c = map(int, input().split())
    a -= 1
    b -= 1
    graph[a] += [[b, c, t]]
    graph[b] += [[a, c, t]]

print(dij(0, graph)[-1])

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值