當我嘗試編碼最短路徑算法時,我遇到了一個奇怪的事情。函數floydWarshall
函數以數組形式生成adjecency矩陣後,main
函數嘗試多次查詢數組(在replicateM_
循環中)。爲什麼函數的結果沒有被重用?
我發現我的代碼非常慢。所以我把traceShow "doing"
放在floydWarshall
的頂部,然後重新找到每個res ! (start,end)
重複調用floydWarshall
。
爲什麼數組每次都會重新生成?
完整的源與樣本輸入:https://gist.github.com/cwyang/27ab81bee731e6d01bb3a7483fdb748e
floydWarshall :: AdjMatrix (Maybe Int) -> AdjMatrix (Maybe Int)
floydWarshall am = traceShow "doing" $ runST $ do
arr <- thaw am :: ST s (STArray s (Vertex,Vertex) (Maybe Int))
sequence_ [ go arr k i j | k <- r, i <- r, j <- r]
freeze arr
where ((minb,_), (maxb,_)) = bounds am
r = [minb..maxb]
go :: STArray s (Vertex,Vertex) (Maybe Int)
-> Vertex -> Vertex -> Vertex -> ST s()
go arr k i j = do
ij <- readArray arr (i,j)
ik <- readArray arr (i,k)
kj <- readArray arr (k,j)
case (ik, kj) of
(Nothing, _) -> return()
(_, Nothing) -> return()
(Just a, Just b) -> case ij of
Nothing -> do
writeArray arr (i,j) $ Just (a+b)
(Just c) -> when (c > a+b) $ do
writeArray arr (i,j) $ Just (a+b)
readInt :: B.ByteString -> Int
readInt = fst . fromJust . B.readInt
main :: IO()
main = do
[n,m] <- rl
edges <- replicateM m $ do
[from,to,weight] <- rl
return (from,to,weight)
[q] <- rl
let am = buildAdjMatrix (1,n) edges
res= floydWarshall am
replicateM_ q $ do
[start,end] <- rl
putStrLn . show $ maybe (-1) id (res ! (start,end))
where rl = map readInt . B.words <$> B.getLine
採樣運行:
$ graph < floyd3.txt hs
"doing" <-- floydWarshall keeps calling
1395
"doing"
975
"doing"
1593
"doing"
1023
"doing"
1521
...
任何機會你有完整的代碼在線?理想情況下,您需要查看核心輸出以查看正在發生的情況,但這僅適用於編譯的內容。另外,你在編譯時使用了哪些標誌? – Alec
Floyd-Warshall是經典的動態規劃算法。你可以找到更好的方法來解決這個問題,使用_Haskell_在這篇文章中:http://jelv.is/blog/Lazy-Dynamic-Programming/ – Shersh
我已經上傳完整的代碼和示例輸入:https://gist.github。 com/cwyang/27ab81bee731e6d01bb3a7483fdb748e –