This is a very standard Knapsack problem from Kattis. Below is a straightforward dynamic programming solution in Haskell:
{-# Language OverloadedStrings #-}
import Control.Arrow ((>>>))
import Data.List (intercalate)
import Data.Array
import Data.Maybe
import qualified Data.ByteString.Lazy.Char8 as C
main = C.interact solve
solve = C.words >>> fmap readInt >>> divideInput
>>> fmap (solveCase >>> toBS)
>>> C.unlines
where readInt = C.readInt >>> fromJust >>> fst
divideInput :: [Int] -> [[Int]]
divideInput [] = []
divideInput (c:n:ls) = (c : n : this) : divideInput that
where (this, that) = splitAt (2*n) ls
solveCase :: [Int] -> [[Int]]
solveCase (c:n:os) = [[length is], is]
where is = recover (n, c) []
recover (i, j) rs | table ! (i, j) == 0 = rs
| table ! (i, j) == table ! (i-1, j) =
recover (i-1, j) rs
| table ! (i, j) == vi + (table ! (i-1, j-wi)) =
recover (i-1, j-wi) ((i-1):rs)
where (vi, wi) = objs ! i
objs :: Array Int (Int, Int)
objs = listArray (1, n) $ pairs os
pairs [] = []
pairs (v:w:os) = (v,w) : pairs os
-- table[i][j] is the max value that can be achieved with
-- objects [1..i] where the total weight of selected
-- objects is <= j.
table :: Array (Int, Int) Int
table = array bnds [(ij, fill ij) | ij <- range bnds]
where
bnds = ((0,0), (n,c))
fill (i, w) | i == 0 || w == 0 = 0
| w < wi = vx
| otherwise = max vx (vy+vi)
where vx = table ! (i-1, w)
vy = table ! (i-1, w - wi)
(vi, wi) = objs ! i
toBS :: [[Int]] -> C.ByteString
toBS [[n], is] = C.intercalate "\n"
[C.pack (show n), C.intercalate " " $ C.pack . show <$> is]
However, the code gives TLE once submitted to Kattis, which seems surprising given its O(Cn) complexity (picking from n objects with maximum capacity C). Does anyone have any suggestions on how to fix this?
I have already tried using mutable Arrays in ST monad. But mutable Arrays doesn't help here, which is not surprising because the DP arrays never need to be updated.
Profiled it on C=2000, n=2000, with values and weights uniform randomly picked between 1 and 20000. It took ~1.16 seconds. Full profile attached below:
523,035,224 bytes allocated in the heap
598,289,064 bytes copied during GC
144,045,528 bytes maximum residency (4 sample(s))
662,056 bytes maximum slop
254 MiB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 464 colls, 0 par 0.374s 0.394s 0.0008s 0.0196s
Gen 1 4 colls, 0 par 0.141s 0.202s 0.0505s 0.1067s
INIT time 0.000s ( 0.004s elapsed)
MUT time 0.651s ( 0.664s elapsed)
GC time 0.515s ( 0.596s elapsed)
EXIT time 0.000s ( 0.001s elapsed)
Total time 1.166s ( 1.265s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 804,028,826 bytes per MUT second
Productivity 55.8% of total user, 52.5% of total elapsed