📜  门|门 CS 1999 |问题 22(1)

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

门|门 CS 1999 |问题 22

简介

本文旨在介绍门|门 CS 1999 |问题 22这道题目,该题为计算机科学领域的经典问题,是关于计算复杂度方面的基础性问题之一。

该问题的提出者为Michael O. Rabin和Dana Scott。

题目描述

考虑一个由n个门组成的迷宫,每扇门上均贴有一个标签。每个标签均为非负整数。迷宫的某些门是被锁上的,而另外一些门是开着的。

你的任务是从起点S到达终点T,并收集所有标签上的数字之和。

你在经过一个门之前可以知道这扇门是否被锁上了,但你无法知道它的标签上写了什么数字。决策是可以根据已知的信息做出的。

请设计算法,找到从ST的一条路径,使路径上经过的所有门的数字之和最大化。

输入格式

输入包含多组测试数据,每组数据第一行为三个整数NLR,分别代表门的数量、起点S的位置和终点T的位置。

接下来N行,每行包含两个整数XY,表示两个门之间的连通情况。如果门之间不能连通,则该门不会包含进来。

接下来一行包含L个整数,代表门是否被锁上。1表示锁上,0表示没锁上。

接下来一行包含N个整数,代表每个门的标签值。

输出格式

输出一个整数,表示从ST的一条路径,其经过的所有门的数字之和的最大值。

样例输入
10 1 10
1 2
2 3
3 4
4 5
1 6
6 7
7 4
4 8
8 9
9 10
0 0 0 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10
样例输出
10
算法思路
  • 定义状态:设$dp(i)$表示到门$i$之前的路径中,数字和的最大值。
  • 状态转移:对于门$i$,若为已解锁状态,则有$dp(i)=\max_{j\in G(i)}{ dp(j) + v_i }$,其中$G(i)$表示所有能够从门$i$到达的门的集合,即$i$的入度所对应的边所连接的门的集合。若为封锁状态,则$dp(i)=-\infty$。
  • 初始化:$dp(S)=v_S$,$dp(i)=-\infty \ (i\neq S)$。
  • 答案:$dp(T)$即为答案。

代码如下:

def solve(n, s, t, e, w):
    """
    n: 门的数量
    s: 起点位置
    t: 终点位置
    e: 门是否被锁上的二进制表示
    w: 门上标签的值
    """
    # 定义状态
    dp = [float('-inf')] * (n + 1)
    dp[s] = w[s]

    # 状态转移
    for i in range(1, n + 1):
        if e[i] == 0:
            for j in range(1, n + 1):
                if i != j and (j, i) in graph:
                    dp[i] = max(dp[i], dp[j] + w[i])

    # 输出答案
    return dp[t]
时间复杂度

本算法的时间复杂度为$O(n^2)$,其中$n$为门的数量。在状态转移时需要遍历所有的门。

参考资料