PAT 1018 Public Bike Management python

主要思路

  1. 找到所有最短的路径(使用Dijkstra)
  2. 对这些路径逐个遍历(使用DFS)
  3. 根据题意算出每条路径所需自行车和剩余自行车
  4. 找到最优路径并输出

使用Dijkstra找到所有的最短路径

需要在基础的Dijkstra上做些更改,把prev向量改成一个矩阵,在更新prev矩阵时需要做出相应的改变。

mmax = 1 << 32 - 1
C_max, N, S_p, M = map(int, input().split())
bikes = list(map(int, input().split()))
bikes.insert(0,0)
perfect = C_max / 2
paths = [[mmax for _ in range(N+1)] for _ in range(N+1)]
for i in range(M):
    start, end, distance = map(int, input().split())
    paths[start][end] = distance
    paths[end][start] = distance

dist = paths[0].copy()
prev = [[] for _ in range(N + 1)]
for i, dd in enumerate(dist):
    if dd != mmax:
        prev[i] = [0]
visited = [False] * (N + 1)
visited[0] = True
for i in range(N + 1):
    min_val = mmax
    for ii, dd in enumerate(dist):
        if (not visited[ii]) and min_val > dd:
            min_val = dd
            k = ii
    visited[k] = True
    for ii, dis in enumerate(paths[k]):
        tmp = mmax if mmax == dis else dis + min_val
        if (not visited[ii]):
            if tmp < dist[ii]:
                prev[ii] = []
                dist[ii] = tmp
                prev[ii].append(k)
            elif tmp == dist[ii]:
                prev[ii].append(k)

使用DFS遍历所有路径

因为每条路径需要独立遍历,单层DFS是不够的,需要使用双层DFS。
在遍历的同时维护最小的所需自行车和剩余自行车

stack, res, need_min, remain_min = [[S_p]], [], mmax, mmax
while len(stack) != 0:
    need, remain, node = 0, 0, stack.pop()
    if node[-1] == 0:
        for ii in range(len(node)-2, -1, -1):
            if bikes[node[ii]] > perfect:
                remain += (bikes[node[ii]] - perfect)
            elif bikes[node[ii]] < perfect:
                gap = perfect - bikes[node[ii]]
                if remain < gap:
                    need += (gap - remain)
                    remain = 0
                else:
                    remain = remain - gap
        if need < need_min or (need == need_min and remain < remain_min):
            res, remain_min, need_min = node, remain, need
    else:
        for sub_node in prev[node[-1]]:
            node.append(sub_node)
            stack.append(node.copy())
            node.pop()

输出结果

把上述过程得到的need_min, remain_min, res 格式化输出即可:

ans = []
for x in res:
    ans.append(str(x))
ans.reverse()
print(f'{0 if need_min == mmax else int(need_min)} {"->".join(ans)} {0 if remain_min == mmax else int(remain_min)}')
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值