SPOILERS: Sto lavorando su http://www.spoj.pl/problems/KNAPSACK/ quindi non sbirciare se non vuoi una soluzione possibile viziata per te.In che modo questa tabella DP memoizzata è troppo lenta per SPOJ?
Il boilerplate:
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
Alcuni tipi e aiutanti di preparare il terreno:
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)
E la funzione primaria:
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
E funziona questo codice; Ho provato a collegare il caso di prova SPOJ e produce il risultato corretto. Ma quando invio questa soluzione a SPOJ (invece di importare MemoCombinator di Luke Palmer, semplicemente copio e incollo le parti necessarie nell'origine inviata), eccede il limite di tempo. =/
Non capisco perché; I asked earlier su un modo efficiente per eseguire lo zaino 0-1, e sono abbastanza convinto che questo sia il più veloce possibile: una funzione memoizzata che calcolerà solo ricorsivamente le sotto-voci di cui ha assolutamente bisogno per produrre il risultato corretto Ho incasinato la memoizzazione in qualche modo? C'è un punto lento in questo codice che mi manca? SPOJ è appena prevenuto contro Haskell?
Ho persino inserito {-# OPTIONS_GHC -O2 #-}
nella parte superiore dell'invio, ma purtroppo non è stato d'aiuto. Ho provato una soluzione simile che utilizza una matrice 2D di Sequence
s, ma è stata anche rifiutata come troppo lenta.
Hai provato a profilare? In generale, non ho trovato che la memoria sia un grande aiuto per la maggior parte dei compiti. Inoltre, usare una sequenza non sembra essere di grande aiuto qui, forse una 'Mappa 'invece? – ivanm
Puoi mostrarci il codice completo con i necessari frammenti di promemoria forniti? Ciò renderebbe più facile la diagnosi del problema. –
L'operazione 'index' è' O (log (min (i, n-i)) '(secondo l'eglefino). Forse dovresti usare una matrice o un vettore. –