文巾解题 LCP 07. 传递信息
1 題目描述
2 解題思路
2.1 動(dòng)態(tài)規(guī)劃
定義動(dòng)態(tài)規(guī)劃的狀態(tài) dp[i][j] 為經(jīng)過(guò) i?輪傳遞到編號(hào) j 的玩家的方案數(shù),其中0≤i≤k,0≤j<n。
由于從編號(hào)?0 的玩家開(kāi)始傳遞,當(dāng)i=0?時(shí)(第0輪),一定位于編號(hào)?0?的玩家,不會(huì)傳遞到其他玩家,因此動(dòng)態(tài)規(guī)劃的邊界情況如下:
對(duì)于傳信息的關(guān)系 [src,dst],如果第 i 輪傳遞到編號(hào) src 的玩家,則第i+1 輪可以從編號(hào) src 的玩家傳遞到編號(hào)dst 的玩家。因此在計(jì)算dp[i+1][dst] 時(shí),需要考慮可以傳遞到編號(hào)dst 的所有玩家。
由此可以得到動(dòng)態(tài)規(guī)劃的狀態(tài)轉(zhuǎn)移方程,其中0≤i<k:
最終得到dp[k][n?1]?即為總的方案數(shù)。
class Solution:def numWays(self, n: int, relation: List[List[int]], k: int) -> int:dp = [[0] * n for _ in range(k + 1)] #每一輪,從0點(diǎn)出來(lái)可以有幾條不同的線路到某一個(gè)點(diǎn)dp[0][0] = 1 #第0輪(初始情況)只有0點(diǎn)可以到達(dá)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]上述實(shí)現(xiàn)的空間復(fù)雜度是 O(kn)。進(jìn)一步分析可以知道,dp[i][] 的值只和 dp[i?1][] 的值有關(guān)。
因此可以將二維數(shù)組變成一維數(shù)組,將空間復(fù)雜度優(yōu)化到 O(n)。
class Solution:def numWays(self, n: int, relation: List[List[int]], k: int) -> int:dp = [0] * ndp[0] = 1for i in range(k):tmp=[0] * nfor edge in relation:src = edge[0]dst = edge[1]tmp[dst] += dp[src]dp=tmpreturn dp[n - 1]2.2 深度優(yōu)先搜索
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為每一個(gè)點(diǎn),value為每一個(gè)點(diǎn)可以連接到的點(diǎn)count=0 #經(jīng)過(guò)k輪可以到達(dá)n-1的路線數(shù)def func(node,k_remain): #node表示目前從那個(gè)點(diǎn)出發(fā) #k_remain表示還剩幾條邊可以連nonlocal countif(k_remain==0 and node==n-1):count+=1 #如果還有0條邊可以連,而且目前到達(dá)了n-1點(diǎn),那么經(jīng)過(guò)k輪可以到達(dá)n-1的路線數(shù)加一elif(k_remain==0):pass #否則,就是到了別的點(diǎn),那么不會(huì)有任何情況else:for i in dit[node]:func(i,k_remain-1) #走到node的鄰居那兒去,剩余的邊數(shù)減一func(0,k)return(count)2.3 廣度優(yōu)先遍歷
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一樣,建立一個(gè)字典queue=[0] #建立一個(gè)隊(duì)列,表示經(jīng)過(guò)time輪目前可以到達(dá)的點(diǎn)(可以有重復(fù))time=0 #目前已經(jīng)走了幾條邊(走了幾輪)while(time<k):tmp_size=len(queue) #當(dāng)前輪有幾個(gè)點(diǎn),一會(huì)把他們一個(gè)一個(gè)彈出隊(duì)列for _ in range(tmp_size):x=queue.pop(0)queue.extend(dit[x]) #當(dāng)前輪的點(diǎn)的鄰居入隊(duì)列time+=1return(queue.count(n-1)) #最后就是經(jīng)過(guò)k輪之后,一共可以到達(dá)的點(diǎn)。里面有幾個(gè)n-1,就說(shuō)明有幾條路線到n-1總結(jié)
以上是生活随笔為你收集整理的文巾解题 LCP 07. 传递信息的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python笔记: 生成器
- 下一篇: 生物计算论文笔记1:The constr