在我看来,不测试的起始索引是那些包含在较长路径中的索引,其中包括所有索引允许的“下一个索引”的所有列表。
所以我首先为每个索引映射了允许的下一个索引,并将它们全部从起始索引组中删除以进行测试:
*Main> indexesIncludedInLongerPaths
[2,0,4,6,1,7,8] (numbers 4,8,7,3,2,7,9)
剩下两个指标需要测试:
*Main> indexesToTest
[3,5] (numbers 0,1)
之后,我从这些起始索引中搜索了所有路径并返回了最长的路径。
*Main> nonDesc matrix
[[1,2,4,7,7,9],[0,2,4,7,7,9]]
哈斯克尔代码:
import Data.List (nub, delete, sortBy, groupBy)
matrix = [8,2,4
,0,7,1
,3,7,9]::[Int]
m = 3
n = 3
neighbors index
| index == 0 = [1,m]
| index == m - 1 = [m-2, 2*m-1, 2*m-2]
| index == m*n - 1 = [m*n-2, m*(n-1)-1, m*(n-1)-2]
| index == m*(n-1) = [m*(n-1)+1, m*(n-2), m*(n-2)+1]
| index < m = [index+1, index-1, index+m, index+m-1, index+m+1]
| index > m*(n-1) = [index+1, index-1, index-m, index-m-1, index-m+1]
| mod index m == 0 = [index+1, index-m, index+m, index-m+1, index+m+1]
| mod (index+1) m == 0 = [index-1, index-m, index+m, index-m-1, index+m-1]
| otherwise = [index+1, index-1, index-m, index+m
,index-m+1, index-m-1, index+m+1, index+m-1]
indexesIncludedInLongerPaths =
nub $ concatMap (\x -> [a | a <- neighbors x
,matrix!!x <= matrix!!a]) [0..length matrix-1]
indexesToTest =
foldr (\a b -> delete a b) [0..length matrix-1] indexesIncludedInLongerPaths
nonDesc matrix = solve indexesToTest [[]] where
solve [] result = last $ groupBy (\a b -> length a == length b)
$ sortBy (\a b -> compare (length a) (length b))
$ map (\x -> map (\y -> matrix!!y) x) (concat result)
solve (x:xs) result =
let paths = solve' [x]
in solve xs (paths:result)
where solve' y =
let b = [a | a <- neighbors (last y)
,notElem a y
,matrix!!(last y) <= matrix!!a]
in if null b
then return y
else do a <- b
solve' (y ++ [a])