文巾解题 LCP 07. 传递信息

1 题目描述

2 解题思路

2.1 动态规划

定义动态规划的状态 dp[i][j] 为经过 i 轮传递到编号 j 的玩家的方案数,其中0≤i≤k,0≤j<n。

由于从编号 0 的玩家开始传递,当i=0 时(第0轮),一定位于编号 0 的玩家,不会传递到其他玩家,因此动态规划的边界情况如下:

对于传信息的关系 [src,dst],如果第 i 轮传递到编号 src 的玩家,则第i+1 轮可以从编号 src 的玩家传递到编号dst 的玩家。因此在计算dp[i+1][dst] 时,需要考虑可以传递到编号dst 的所有玩家。

由此可以得到动态规划的状态转移方程,其中0≤i<k:

最终得到dp[k][n−1] 即为总的方案数。

class Solution:
    def numWays(self, n: int, relation: List[List[int]], k: int) -> int:
        dp = [[0] * n for _ in range(k + 1)]
#每一轮,从0点出来可以有几条不同的线路到某一个点

        dp[0][0] = 1
#第0轮(初始情况)只有0点可以到达

        for i in range(k):
            for edge in relation:
                src = edge[0]
                dst = edge[1]
                dp[i + 1][dst] += dp[i][src]
#每一轮的情况由上一轮决定
        return dp[k][n - 1]

上述实现的空间复杂度是 O(kn)。进一步分析可以知道,dp[i][] 的值只和 dp[i−1][] 的值有关。

因此可以将二维数组变成一维数组,将空间复杂度优化到 O(n)。

class Solution:
    def numWays(self, n: int, relation: List[List[int]], k: int) -> int:
        dp = [0] * n
        dp[0] = 1
        for i in range(k):
            tmp=[0] * n
            for edge in relation:
                
                src = edge[0]
                dst = edge[1]
                tmp[dst] += dp[src]

            dp=tmp
        return dp[n - 1]

2.2 深度优先搜索

class Solution:
    def numWays(self, n: int, relation: List[List[int]], k: int) -> int:
        dit={}
        for i in relation:
            if i[0] in dit:
                dit[i[0]].append(i[1])
            else:
                dit[i[0]]=[i[1]]
        for i in range(n):
            if i not in dit:
                dit[i]=[]
#字典,字典的key为每一个点,value为每一个点可以连接到的点

        count=0
#经过k轮可以到达n-1的路线数

        def func(node,k_remain):
#node表示目前从那个点出发
#k_remain表示还剩几条边可以连

            nonlocal count
            if(k_remain==0 and node==n-1):
                count+=1
#如果还有0条边可以连,而且目前到达了n-1点,那么经过k轮可以到达n-1的路线数加一
            elif(k_remain==0):
                pass
#否则,就是到了别的点,那么不会有任何情况
            else:
                for i in dit[node]:
                    func(i,k_remain-1)
#走到node的邻居那儿去,剩余的边数减一
        func(0,k)
        return(count)

2.3 广度优先遍历

class Solution:
    def numWays(self, n: int, relation: List[List[int]], k: int) -> int:
        dit={}
        for i in relation:
            if i[0] in dit:
                dit[i[0]].append(i[1])
            else:
                dit[i[0]]=[i[1]]
        for i in range(n):
            if i not in dit:
                dit[i]=[]
#和2.2一样,建立一个字典

        queue=[0]
#建立一个队列,表示经过time轮目前可以到达的点(可以有重复)
        time=0
#目前已经走了几条边(走了几轮)

        while(time<k):
            tmp_size=len(queue)
#当前轮有几个点,一会把他们一个一个弹出队列
            for _ in range(tmp_size):
                x=queue.pop(0)
                queue.extend(dit[x])
#当前轮的点的邻居入队列
            time+=1

        return(queue.count(n-1))
#最后就是经过k轮之后,一共可以到达的点。里面有几个n-1,就说明有几条路线到n-1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UQI-LIUWJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值