文巾解题 LCP 07. 传递信息
Posted 刘文巾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文巾解题 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
以上是关于文巾解题 LCP 07. 传递信息的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode LCP 07. 传递信息 / NC111 最大数 / NC16 判断二叉树是否对称 / NC13 二叉树的最大深度