Algorithm 在Haskell中求解代码chef(chef and Way)上的CHRL4
我试图在Haskell中解决这个问题,但codechef编译器一直说这是错误的答案。问题如下:Algorithm 在Haskell中求解代码chef(chef and Way)上的CHRL4,algorithm,haskell,functional-programming,Algorithm,Haskell,Functional Programming,我试图在Haskell中解决这个问题,但codechef编译器一直说这是错误的答案。问题如下: import qualified Data.ByteString.Char8 as B import Data.Maybe (fromJust) findMinIndex x index minIndex n | index == n = minIndex | (x!!index) < (x!!minIndex) = findMinIndex x (index+1)
import qualified Data.ByteString.Char8 as B
import Data.Maybe (fromJust)
findMinIndex x index minIndex n
| index == n = minIndex
| (x!!index) < (x!!minIndex) = findMinIndex x (index+1) index n
| otherwise = findMinIndex x (index+1) minIndex n
minCost [] _ = 1
minCost (x:xs) k = let indexList = take k xs
minIndex = findMinIndex indexList 0 0 (length indexList)
in x * minCost(drop minIndex xs) k
main :: IO()
main = do
t <- B.getContents
let inputs = B.lines t
let firstLine = inputs !! 0
let secondLine = inputs !! 1
let [n,k] = map (fst . fromJust . B.readInt) $ B.split ' ' firstLine
let specialNums = reverse $ map (fst . fromJust . B.readInteger) $ B.split ' ' secondLine
putStrLn $ show ((minCost specialNums k) `mod` 1000000007)
在拜访了一位儿时的朋友后,这位厨师想回家。朋友住在第一条街,厨师自己住在第N条街(也是最后一条街)。他们的城市有点特别:当且仅当1您的算法不总是为所有输入提供最小乘积时,您可以从X街移动到Y街,例如:
5 2
3 2 3 2 3
这本书通篇解释了这个问题,你真的应该再读一遍
这个问题基本上是一个最短路径问题,街道是顶点,从街道到街道的可能移动是图的边,边的权重仅由尾部的特殊值决定。虽然总移动成本被定义为产品,但不是所有成本的总和,但问题可以通过取所有特殊值的对数来标准化,因为
a*b=exp(log(a)+log(b))
给定对数是单调递增函数,最小乘积就是对数的最小和
在社论中,编辑选择了Dijkstra的算法,但在进行了日志转换之后,这将是一个标准的最短路径问题,可以用您喜欢的任何最短路径算法来解决
在Haskell中有许多Dijkstra算法的实现,我在Hackage中发现了两个,一个。解析和图形初始化代码非常简单
import Control.Monad (foldM)
import Control.Monad.ST
import Data.Array
import Data.Array.MArray
import Data.Array.ST
import Data.Function (on)
import Data.IntMap.Strict as M
import Data.List (groupBy)
import Data.Set as S
-- Code from http://rosettacode.org/wiki/Dijkstra's_algorithm#Haskell
dijkstra :: (Ix v, Num w, Ord w, Bounded w) => v -> v -> Array v [(v,w)] -> (Array v w, Array v v)
dijkstra src invalid_index adj_list = runST $ do
min_distance <- newSTArray b maxBound
writeArray min_distance src 0
previous <- newSTArray b invalid_index
let aux vertex_queue =
case S.minView vertex_queue of
Nothing -> return ()
Just ((dist, u), vertex_queue') ->
let edges = adj_list Data.Array.! u
f vertex_queue (v, weight) = do
let dist_thru_u = dist + weight
old_dist <- readArray min_distance v
if dist_thru_u >= old_dist then
return vertex_queue
else do
let vertex_queue' = S.delete (old_dist, v) vertex_queue
writeArray min_distance v dist_thru_u
writeArray previous v u
return $ S.insert (dist_thru_u, v) vertex_queue'
in
foldM f vertex_queue' edges >>= aux
aux (S.singleton (0, src))
m <- freeze min_distance
p <- freeze previous
return (m, p)
where b = bounds adj_list
newSTArray :: Ix i => (i,i) -> e -> ST s (STArray s i e)
newSTArray = newArray
shortest_path_to :: (Ix v) => v -> v -> Array v v -> [v]
shortest_path_to target invalid_index previous =
aux target [] where
aux vertex acc | vertex == invalid_index = acc
| otherwise = aux (previous Data.Array.! vertex) (vertex : acc)
-- Code I wrote
instance Bounded Double where
minBound = -1e100
maxBound = 1e100
constructInput :: Int -> Int -> M.IntMap Integer -> Array Int [(Int, Double)]
constructInput n k specMap =
let
specMap' = fmap (log . fromIntegral) specMap
edges = [(src, [(dest, specMap' M.! dest) | dest <- [src+1..src+k], dest <= n]) | src <- [1..n]]
in
array (1, n) edges
main :: IO ()
main = do
rawInput <- getContents
let
[l, l'] = lines rawInput
[n,k] = fmap read . words $ l
specs = fmap read . words $ l'
specMap = M.fromList $ [1..n] `zip` specs
adj_list = constructInput n k specMap
(_, previous) = dijkstra 1 0 adj_list
path = shortest_path_to n 0 previous
weight = (product $ fmap (specMap M.!) path) `mod` 1000000007
print weight
import Control.Monad(foldM)
进口管制站
导入数据。数组
导入Data.Array.MArray
导入Data.Array.ST
导入数据。函数(打开)
将Data.IntMap.Strict导入为M
导入数据列表(groupBy)
导入数据。设置为S
--代码来自http://rosettacode.org/wiki/Dijkstra's#u算法#Haskell
dijkstra::(Ix v,Num w,Ord w,Bounded w)=>v->v->Array v[(v,w)]->(Array v w,Array v v)
dijkstra src无效索引调整列表=runST$do
最小距离>=aux
辅助(S.singleton(0,src))
m e->ST s(斯塔雷s i e)
newSTArray=newArray
最短路径到::(Ix v)=>v->v->Array v->[v]
到目标的最短路径无效索引先前=
辅助目标[]在哪里
辅助顶点acc |顶点==无效_索引=acc
|否则=辅助(上一个数据数组!顶点)(顶点:acc)
--我写的代码
实例有界双精度
minBound=-1e100
maxBound=1e100
constructInput::Int->Int->M.IntMap Integer->Array Int[(Int,Double)]
构造输入n k specMap=
让
specMap'=fmap(log.fromIntegral)specMap
edges=[(src,[(dest,specMap'M.!dest)| dest我不知道您需要多少提示,但您的算法并不总是找到最佳(=最小乘积)路径。谢谢。几天后我意识到了这一点并更正了代码。现在它可以工作了。再次感谢您