📜  门|门CS 2010 |第 53 题(1)

📅  最后修改于: 2023-12-03 14:58:36.991000             🧑  作者: Mango

门|门CS 2010 |第 53 题

这是一道算法题目,需要使用递归和图论的思想解决。

题目描述

有 $n$ 个门,门上标号为 $1$ 到 $n$,其中第 $i$ 个门会通向第 $a_i$ 个门或者第 $b_i$ 个门。你从门 $1$ 出发,每走过一扇门就需要扣除 $p$ 的代价,求到达 $n$ 号门的最小代价。

解题思路

首先可以考虑使用递归的思想,从门 $1$ 出发,每次选择走 $a_i$ 或者 $b_i$ 活着停在当前门不动。

但是,这样会导致重复计算,因为可以经过多次走同一个门。因此,在计算过程中,需要将访问过的门标记一下,避免重复计算。

此外,题目中给出的门与门之间的关系也是一个图,因此可以使用图论的知识来求解。可以将每个门看作一个节点,门与门之间的关系看作边,然后使用DFS或者BFS来求解最短路径。

最后需要注意的一点是,题目中给出的门编号是从 $1$ 开始的,而在数组中的下标是从 $0$ 开始的,因此需要做一下转换。

代码实现
def dfs(cur, cost, visited, doors):
    if cur == n:
        return cost
    if visited[cur]:
        return float('inf')
    visited[cur] = True
    res = min(dfs(doors[cur][0]-1, cost+p, visited, doors),
              dfs(doors[cur][1]-1, cost+p, visited, doors),
              dfs(cur, cost+p, visited, doors))
    visited[cur] = False
    return res

if __name__ == '__main__':
    n, p = map(int, input().split())
    a = list(map(int, input().split()))
    b = list(map(int, input().split()))
    doors = list(zip(a, b))
    visited = [False for i in range(n)]
    print(dfs(0, 0, visited, doors))

以上是使用递归实现的代码,在计算过程中使用了visited数组来标记访问过的门。

from queue import Queue

def bfs(n, cost, doors, visited):
    q = Queue()
    q.put((0, 0))
    visited[0] = True
    while not q.empty():
        cur, cur_cost = q.get()
        if cur == n-1:
            return cur_cost
        for next_door in doors[cur]:
            if not visited[next_door]:
                visited[next_door] = True
                q.put((next_door, cur_cost+p))
        if not visited[cur]:
            visited[cur] = True
            q.put((cur, cur_cost+p))
    return -1
if __name__ == '__main__':
    n, p = map(int, input().split())
    a = list(map(int, input().split()))
    b = list(map(int, input().split()))
    doors = [[] for i in range(n)]
    for i in range(n-1):
        doors[a[i]-1].append(b[i]-1)
        doors[b[i]-1].append(a[i]-1)
    visited = [False for i in range(n)]
    print(bfs(n, 0, doors, visited))

以上是使用BFS实现的代码,在计算过程中使用了visited数组来标记访问过的门,使用队列来进行广度优先搜索。

总结

本题的重点在于如何防止重复计算以及如何将题目中的门与门之间的关系转换为图。如果能够理解递归和图论的思想,那么就可以轻松地解决这个问题。