Как эта запомненная таблица DP слишком медленна для SPOJ?

SPOILERS: Я работаю над http://www.spoj.pl/problems/KNAPSACK/, так что не подглядывай, если не хочешь, чтобы возможное решение было для тебя испорчено.

Блок-схема:

import Data.Sequence (index, fromList)
import Data.MemoCombinators (memo2, integral)

main = interact knapsackStr

knapsackStr :: String -> String
knapsackStr str = show $ knapsack items capacity numItems
  where [capacity, numItems] = map read . words $ head ls
        ls = lines str
        items = map (makeItem . words) $ take numItems $ tail ls

Некоторые типы и помощники для настройки сцены:

type Item = (Weight, Value)
type Weight = Int
type Value = Int

weight :: Item -> Weight
weight = fst

value :: Item -> Value
value = snd

makeItem :: [String] -> Item
makeItem [w, v] = (read w, read v)

И основная функция:

knapsack :: [Item] -> Weight -> Int -> Value
knapsack itemsList = go
  where go = memo2 integral integral knapsack'
        items = fromList $ (0,0):itemsList
        knapsack' 0 _ = 0
        knapsack' _ 0 = 0
        knapsack' w i | wi > w    = exclude
                      | otherwise = max exclude include
          where wi = weight item
                vi = value item
                item = items `index` i
                exclude = go w (i-1)
                include = go (w-wi) (i-1) + vi

И этот код работает; я попробовал подключить тестовый пример SPOJ и он выдаст правильный результат. Но когда я отправляю это решение в SPOJ (вместо импорта MemoCombinators Люка Палмера, я просто копирую и вставляю необходимые части в присланные исходники), это превышает срок. =/

Я не понимаю почему; я спрашивал ранее об эффективном способе выполнения 0-1 кнэпсэка, и я вполне уверен, что это примерно так же быстро, как и получается: memoized функция, которая будет только рекурсивно вычислять подзаписи, которые ей абсолютно необходимы для получения корректного результата. Я как-то испортил запоминание? Есть ли в этом коде медленный пункт, который я пропустил? SPOJ просто предвзято настроен против Хаскелла?

Я даже поставил {-# OPTIONS_GHC -O2 #-} в верхнюю часть представления, но, увы, это не помогло. Я пробовал подобное решение, использующее 2D массив из Sequences, но оно также было отвергнуто как слишком медленное.

14
задан Community 23 May 2017 в 12:16
поделиться