Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Haskell でアルゴリズムを抽象化する / 関数型言語で競技プログラミング

Haskell でアルゴリズムを抽象化する / 関数型言語で競技プログラミング

Competitive programming with Haskell
Functional Festival 2025 in TOKYO

Avatar for Naoya Ito

Naoya Ito

June 14, 2025

More Decks by Naoya Ito

Other Decks in Programming

Transcript

  1. ࿩͍ͨ͜͠ͱ • )BTLFMM ͰڝٕϓϩάϥϛϯάʹࢀՃ͍ͯ͠ΔɻΞϧΰϦζϜΛந৅Խ͢Δͱɺͦͷ࣮૷͕ ࣅͨΑ͏ͳΠϯλϑΣʔεʹͳΔ͜ͱΛܦݧͨ͠ – ߴ֊ؔ਺ͱͯࣸ͠૾ Gͱ݁߹ͷೋ߲ԋࢉ͕ύϥϝʔλͱͯ͠Α͘දΕΔ • ͦΕ͸ۮવͳͷ͔ɺ͍΍ɺۮવͰ͸ͳ͍

    – )BTLFMMͷࠜఈʹ͋Δ࠶ؼσʔλߏ଄ɺͦΕʹ࠷దͳૢ࡞Ͱ͋Δࣸ૾ͱ৞ΈࠐΈ NBQSFEVDF • ࣸ૾ͱ৞ΈࠐΈʹΑΔؔ਺ͷΠϯλϑΣʔε͔ΒΞϧΰϦζϜͷ୅਺తߏ଄͕ݟ͑Δ • ؔ਺ܕϓϩάϥϛϯάɺ)BTLFMM͸ΞϧΰϦζϜΛΑΓந৅౓ߴ͘ଊ͑ΔࢥߟΛิॿͯ͘͠ ΕΔ
  2. ໨࣍ • ࣸ૾ NBQ Ͱ໰୊Λղ͘ • ྦྷੵ࿨ uuu GPMETDBOMʹΑΔʮ৞ΈࠐΈʯ •

    ΞϧΰϦζϜΛந৅Խ͢Δ uuu ೋ෼୳ࡧΛߴ֊ؔ਺Ͱந৅Խ͢Δ • #'4Λந৅Խ͢Δuuu ؔ਺ GΛʮ͋Δঢ়ଶ͔Β࣍ͷঢ়ଶ΁ͷঢ়ଶભҠʯͱଊ͑Δ • ಈతܭը๏Λ )BTLFMMͰΠϛϡʔλϒϧʹղ͘ uuuঢ়ଶۭؒͷ৞ΈࠐΈɺͦͯ͠୅਺తߏ଄ ͕ݟ͑Δ • ͳͥΞϧΰϦζϜΛந৅Խ͢ΔͱɺNBQSFEVDF GPME ΍୅਺తߏ଄͕ uuu ؔ਺ܕϓϩά ϥϛϯάɺ)BTLFMM͕ͦΕΛଅ͢
  3. ࣸ૾ͱ݁߹ ू໿ uuu NBQSFEVDF GPME • ؔ਺ܕϓϩάϥϛϯάͰ͸ʮࣸ૾ͱ݁߹ ू໿ ʯͷϝϯλϧϞσϧͰ໰୊Λղ͘ •

    ࣸ૾ͱ݁߹ ू໿ uuu NBQSFEVDF GPME • ͳͥ NBQSFEVDF͔ – )BTLFMMͷෆมσʔλߏ଄͸୅਺తσʔλܕʹΑΔ࠶ؼσʔλߏ଄ – ࠶ؼσʔλߏ଄ͷૢ࡞ʹ͸ NBQSFEVDF – -*41ͷ௚ײ͔Βʜ ͋ͱͰ
  4. #'4ʹ౉͍ͯ͠Δؔ਺ GͷҙຯΛߟ͑ͯΈΔ let dist = bfs f (+) (-1) bounds

    [(1, 0 :: Int)] • f Λهड़͢Δ͚ͩͰ໰୊͕ղ͚Δ͕ɺf ͸Կऀ? • (v -> [(v, e)]) • (ঢ়ଶ -> [(࣍ͷঢ়ଶ, ભҠίετ)]) ͱ͍͏ঢ়ଶભҠͷࣸ૾ ঢ়ଶ͔ΒભҠީิ΁ͷࣸ૾  ͱߟ͑Δ͜ͱ͕Ͱ͖Δ
  5. ݁߹ͷ࢓ํͱঢ়ଶભҠͷؔ਺ ͋ͱॳظঢ়ଶ Λએݴ͢Ε͹ɺ%1͕ղ͚Δ main = do [n, wx] <- getInts

    items <- replicateM n getTuple let dp = accumArrayDP @UArray f max 0 (0, wx) [(0, 0)] items where f (w, acc) (wi, vi) = [(w, acc), (w + wi, acc + vi)] print $ maximum (elems dp)
  6. ͳͥͦΕ͕ɺ୅਺తߏ଄ͱ݁ͼͭ͘ͷ͔ • લड़ͷ௨Γ ࠶ؼతσʔλߏ଄͸ࣸ૾ͱ݁߹ʹࣗવʹؐݩͰ͖Δ • ঢ়ଶͷʮ఻ൖʯͱʮू໿ʯ͸୅਺తੑ࣭Λඞཁͱ͢Δ – ʮ఻ൖʯ֤ঢ়ଶΛ৽͍͠ঢ়ଶʹࣸ͢ ˠࣸ૾ –

    ʮू໿ʯෳ਺ͷ݁ՌΛҰͭʹ·ͱΊΔ ˠ݁߹ – ͜Ε͕݁߹తͰͳ͚Ε͹࠶ؼɾޮ཰Խ͕೉͍͠ ˠ୅਺తߏ଄ͷཁ੥ ΞϧΰϦζϜΛந৅Խ͢Δͱࣸ૾ͱ݁߹͕ܭࢉͷຊ࣭తͳߏ੒ཁૉͱͯ͠ݱΕΔ ঢ়ଶۭؒΛू߹ͱΈͳ͢ͱɺ୅਺తߏ଄ʢ'VODUPS .POPJE 4FNJSJOHʣʹରԠ͢Δ )BTLFMMͷܕͱߴ֊ؔ਺͸ɺͦͷߏ଄ΛࣗવʹΠϯλϑΣʔεͱͯ͠࿐ग़ͤ͞Δ ந৅Խ͸ʮܭࢉͷ୅਺ʯΛՄࢹԽ͢ΔաఔͰ΋͋Δ
  7. 8 12 40 4 6 20 2 3 10 ۮ਺͔͠ͳ͍ͷͰૢ࡞͢Δ

    ·ͩۮ਺͔͠ͳ͍ͷͰૢ࡞͢Δ ح਺͕ग़͖ͯͨͷͰऴΘΓ
  8. ໋ྩܕϓϩάϥϛϯάͰ࣮૷ uuu ୹໋σʔλߏ଄Λ܁Γฦ͠ॻ͖׵͑ͯ౴͑ΛಘΔ count = 0 while all(a % 2

    == 0 for a in as): for i in range(n): as[i] //= 2 count += 1 print(count)
  9. ۠ؒ࿨ʹ͸ྦྷੵ࿨Λ࢖͏ͱΑ͍ let ds = [3, 1, 4, 1, 5, 9]

    :: [Int] s = scanl' (+) 0 ds -- [0, 3, 4, 8, 9, 14, 23]
  10. ໋ྩతʹ࣮૷͢Δ p, q = input().split() ds = [3, 1, 4,

    1, 5, 9] # 累積和 s = [0] * 7 for i in range(6): s[i + 1] = s[i] + ds[i] pi = ord(p) - ord('A') qi = ord(q) - ord('A') print(abs(s[qi] - s[pi]))
  11. ؔ਺ܕͰ࣮૷͢Δ main :: IO () main = do (p, q)

    <- auto @(Char, Char) let ds = [3, 1, 4, 1, 5, 9] :: [Int] s = listArray @UArray ('A', 'G') $ scanl' (+) 0 ds ans = s ! q - s ! p print $ abs ans
  12. ݁߹ ͷ࠶ؼతͳؔ਺ద༻ uuu ʮ৞ΈࠐΈʯ foldl (+) 0 [3, 1, 4,

    1, 5, 9] ==> ((((((0 + 3) + 1) + 4) + 1) + 5) + 9) scanl (+) 0 [3, 1, 4, 1, 5, 9] [ 0 , (0 + 3) , ((0 + 3) + 1) , (((0 + 3) + 1) + 4) , ((((0 + 3) + 1) + 4) + 1) , (((((0 + 3) + 1) + 4) + 1) + 5) , ((((((0 + 3) + 1) + 4) + 1) + 5) + 9) ]
  13. վΊͯ )BTLFMMͰͷྦྷੵ࿨ uuu TDBOMΛΈͯΈΔ let ds = [3, 1, 4,

    1, 5, 9] :: [Int] s = scanl' (+) 0 ds -- [0, 3, 4, 8, 9, 14, 23 scanl' :: (b -> a -> b) -> b -> [a] -> [b] • ࠶ؼతʹ݁߹Λద༻͢Δɺͱ͍͏ྦྷੵܭࢉ ৞ΈࠐΈ Λந৅Խͨ͠ͷ͕ TDBOM • TDBOMͷΠϯλϑΣʔεʹ͸݁߹ԋࢉ͕ύϥϝʔλͱͯ͠දΕ͍ͯΔ – ͳΒྦྷੵ࿨ – NBYͳΒྦྷੵ NBY – NJOͳΒྦྷੵ NJO – YPSͳΒྦྷੵ YPS
  14. ࣸ૾ͱ݁߹ ू໿ uuu NBQSFEVDF GPME • ؔ਺ܕϓϩάϥϛϯάͰ͸ʮࣸ૾ͱ݁߹ ू໿ ʯͷϝϯλϧϞσϧͰ໰୊Λղ͘ •

    ࣸ૾ͱ݁߹ ू໿  NBQSFEVDF GPME • ͳͥ NBQSFEVDF͔ – )BTLFMMͷෆมσʔλߏ଄͸୅਺తσʔλܕʹΑΔ࠶ؼσʔλߏ଄ – ࠶ؼσʔλߏ଄ͷૢ࡞ʹ͸ NBQSFEVDF – -*41ͷ௚ײ͔Βʜ ͋ͱͰ
  15. ୯ௐੑ͕͋ΔͷͰɺڥքΛఆΊΔ͜ͱ͕Ͱ͖Δ        Ҏ্ uuu

    ճ Ҏ্ uuuճ Ҏ্ uuu ճ Ҏ্ uuuճ Ҏ্ uuu ճ Ҏ্ uuu ճ ͜͜·Ͱ৚݅Λຬͨ͢ɺҎ߱͸ຬͨ͞ͳ͍ YҎ্ͷཁૉ͕ YճҎ্දΕΔ͔
  16. ೋ෼୳ࡧͰղ͚·͢ɻͰ΋ɺίϯςετதʹೋ෼୳ࡧΛॻ͘ͱόάΒ͕ͤͪ main :: IO () main = do _ <-

    getInt as <- getInts let binSearch (ok, ng) | abs (ng - ok) == 1 = ok | otherwise = do let m = (ok + ng) `div` 2 count = length $ filter (>= m) as if count >= m then binSearch (m, ng) else binSearch (ok, m) print $ binSearch (0, 10 ^ 18)
  17. ຖճॻ͔ͳ͍͍ͯ͘Α͏ɺந৅Խ͠·͢ ˠߴ֊ؔ਺ G͕දΕΔ -- | 左が true / 右が false

    で境界を引く bisect2 :: (Integral a) => (a, a) -> (a -> Bool) -> (a, a) bisect2 (ok, ng) f | abs (ng - ok) == 1 = (ok, ng) | f m = bisect2 (m, ng) f | otherwise = bisect2 (ok, m) f where m = (ok + ng) `div` 2 let (ok, _) = bisect2 (0, 10 ^ 18) (¥x -> countBy (>= x) as >= x) print ok
  18. ৚݅ؔ਺ G͸ࣸ૾ͱΈͳͤΔ • ೋ෼୳ࡧ͸ʮڥքΛҾ͘৚݅ʯΛؔ਺ GͰ౉͢Α͏ந৅ԽͰ͖Δ • (a -> Bool) Λʮ஋

    ੔਺ ͔Β ৚݅Λຬ͔ͨ͢Ͳ͏͔΁ͷࣸ૾ʯͱଊ͑Δ͜ͱ͕Ͱ͖Δ • ΞϧΰϦζϜΛந৅Խͨ͠Βͦ͜ʹࣗવͱࣸ૾ G͕දΕͨ bisect2 :: (Integral a) => (a, a) -> (a -> Bool) -> (a, a)
  19. άϥϑΛʮྡ઀Ϧετʯʹߏ଄Խͯ͠ #'4 ෯༏ઌ୳ࡧ ͢Δ main = do [n, m] <-

    getInts uvs <- replicateM m getTuple -- 1 => [(2, 1), (4, 1)] という構造の「隣接リスト」にする let g = accumArray @Array (flip (:)) [] (1, n) $ concatMap (¥(u, v) -> [(u, (v, 1)), (v, (u, 1))]) uvs -- 幅優先探索する dist = bfs g [(1, 0)] for_ [1 .. n] $ ¥s -> print $ dist ! s
  20. ࢀߟ ઌͷ #'4 ͷ࣮૷ bfs :: (Ix v, IArray a

    [(v, e)], Num e, Eq e) => a v [(v, e)] -> [(v, e)] -> Array v e bfs g v0s = runSTArray $ do dist <- newArray (bounds g) (-1) for_ v0s $ ¥(v0, d0) -> do writeArray dist v0 d0 aux (Seq.fromList [v0 | (v0, _) <- v0s]) dist return dist where aux Empty _ = return () aux (v :<| queue) dist = do acc <- readArray dist v us <- filterM ( ¥(u, _) -> (fmap (== -1) . readArray dist) u ) (g ! v) queue' <- foldForM queue us $ ¥q (u, w) -> do writeArray dist u $! acc + w return $ q |> u aux queue' dist ༨ஊ ࢲ͸͜Ε͙Β͍ʹͳΔͱίϯςετ தʹ͸ॻ͖ͨ͘ͳ͍ͷͰϥΠϒϥϦԽ͠· ͕͢ɺ$ ΍1ZUIPOͰ΍ͬͯΔਓ͸ຖ ճ#'4ΛιϥͰهड़ͯͨ͠Γ͠·͢
  21. ந৅౓Λ্͛Δ uuu άϥϑͷભҠΛ֎෦͔Β஫ೖͰ͖ΔΑ͏ʹ͢Δ let dist = bfs (g !) (+)

    (-1) (bounds g) [(1, 0)] • (g !) uuuʮ௖఺W͔ΒḷΕΔ௖఺͸ ʯͱ͍͏ࣸ૾ G – ʮ௖఺ ͔Β͸ɺ௖఺ ̎ ͱ௖఺ ΁ɺͦΕͧΕॏΈ ͰભҠͰ͖ΔʯΛهड़͢Δؔ਺ – f v = g ! v • ڑ཭ͷ݁߹ԋࢉ (+)
  22. #'4ͷ࣮૷Λม͑Δ͜ͱͳ͘ɺؔ਺ GΛهड़͢Δ͚ͩͰ໰୊͕ղ͚Δ main = do [h, w] <- getInts grid

    <- getCharGrid ((1, 1), (h, w)) let dist = bfs f (+) (-1) (bounds grid) [((1, 1), 0)] where f v = [ (u, 1) | d <- [(1, 0), (0, 1), (-1, 0), (0, -1)], let u = v + d, inRange (bounds grid) u, case (grid ! v, grid ! u) of ('s', 'n') -> True ('n', 'u') -> True ('u', 'k') -> True ('k', 'e') -> True ('e', 's') -> True _ -> False ] printYn $ dist ! (h, w) /= -1 ʮϚε WˠW͔Β౸ୡͰ͖ΔϚε VͷϦετʯ ͱ͍͏ࣸ૾ άϦουͷ্Լࠨӈʹ৚݅Λຬͨ͢ભҠઌ͕͋ΔͳΒ ͦΕΛྻڍ
  23. main = do [a, n] <- getInts let bounds =

    (1, 10 ^ 6 + 1 :: Int) let dist = bfs f (+) (-1) bounds [(1, 0 :: Int)] where f x | x >= 10 && x `mod` 10 /= 0 = [(x', 1) | x' <- [rotate x, a * x], inRange bounds x'] | otherwise = [(a * x, 1) | inRange bounds (a * x)] rotate y = let ys = toDigits 10 y in fromDigits 10 (last ys : init ys) print $ dist ! n ΍͸Γؔ਺ GΛهड़͢Δ͜ͱͰ໰୊͕ղ͚Δ
  24. վΊͯ #'4ʹ౉͍ͯ͠Δؔ਺ GͷҙຯΛߟ͑ͯΈΔ let dist = bfs f (+) (-1)

    bounds [(1, 0 :: Int)] • f Λهड़͢Δ͚ͩͰ໰୊͕ղ͚Δ͕ɺf ͸Կऀ? • (v -> [(v, e)]) • (ঢ়ଶ -> [(࣍ͷঢ়ଶ, ભҠίετ)]) ͱ͍͏ঢ়ଶભҠͷࣸ૾ ঢ়ଶ͔ΒભҠީิ΁ͷࣸ૾  ͱߟ͑Δ͜ͱ͕Ͱ͖Δ
  25. ༨ஊ )BTLFMM Ҏ֎Ͱ΋͜Μͳ෩ʹ #'4Λந৅ԽͰ͖Δ • Θ͔Βͳ͍͚Ͳɺ؆୯Ͱ͸ͳͦ͞͏ • ભҠΛʮঢ়ଶભҠͷؔ਺ʯͱ͢Δ͜ͱ͸Ͱ͖Δ • ঢ়ଶۭؒͷߏ଄

    ࣍ݩ ΛύϥϝʔλԽ͢Δ͜ͱͱɺύϑΥʔϚϯεΛཱ྆͢Δͷ͕೉͍͔͠ ΋ – )BTLFMMͷ "SSBZ͸࣍ݩΛύϥϝʔλԽͰ͖Δ
  26. for (int j = 0; j <= W; ++j) dp[0][j]

    = 0; for (int i = 0; i < N; ++i) { for (int j = 0; j <= W; ++j) { if (j >= w[i]) dp[i+1][j] = max(dp[i][j-w[i]] + v[i], dp[i][j]); else dp[i+1][j] = dp[i][j]; } } cout << dp[N][W] << endl; ໋ྩతͳ࣮૷ uuu Մมͳೋ࣍ݩ഑ྻΛ༻ҙͯ͠ॻ͖׵͑Δ
  27. Ұͭલͷঢ়ଶΛ࣍ͷঢ়ଶʹભҠͤ͞ΔɻͦΕΛ࠶ؼతʹ uuu GPME͡ΌΜ main = do [n, wx] <- getInts

    items <- replicateM n getTuple -- 初期状態の状態空間 let dp0 = accumArray @UArray max minBound (0, wx) [(0, 0 :: Int)] -- 状態空間を、再帰的に状態遷移させる let dp' = foldl' f dp0 items where f dp (wi, vi) = accum max dp [(w + wi, acc + vi) | (w, acc) <- assocs dp, inRange (bounds dp) (w + wi)] print $ maximum (elems dp) Մม഑ྻΛߋ৽͢Δͱ͍͏໋ ྩతͳ࣮૷Ͱ͸ͳ͘ɺෆมͳ ஋Λ৞ΈࠐΜͰ͍͘ɺͱ͍͏ )BTLFMMΒ͍࣮͠૷ʹ
  28. ໰୊ʹݻ༗ͷ෦෼ΛύϥϝʔλԽ͠ɺGPMEʹΑΔ %1ܭࢉΛந৅Խ͢Δ -- 畳み込みDP -- ex) accumArrayDP @UArray f max

    minBound (0, wx) [(0, 0)] wvs accumArrayDP :: ( IArray a e, Ix v, Eq e, Show e, Show v, Show (a v e), Foldable t ) => ((v, e) -> x -> [(v, e')]) -> -- 状態遷移関数 f v / x をみて v の次の遷移可能性を返す (e -> e' -> e) -> -- 緩和の二項演算 e -> -- 初期値 (0, minBound, maxBound, False など) (v, v) -> -- 状態空間の下界、上界 [(v, e')] -> -- 開始時点の状態 t x -> -- 入力 (時間遷移) a v e -- Array or UArray accumArrayDP f combine initial (l, u) v0s xs = let dp = accumArray combine initial (l, u) v0s in foldl' transition dp xs where transition dp x = accumArray combine initial (l, u) $ concatMap (filter (inRange (bounds dp) . fst) . (`f` x)) (assocs dp)
  29. φοϓβοΫ໰୊͸͜͏ղ͚Δ main = do [n, wx] <- getInts items <-

    replicateM n getTuple let dp = accumArrayDP @UArray f max 0 (0, wx) [(0, 0)] items where f (w, acc) (wi, vi) = [(w, acc), (w + wi, acc + vi)] print $ maximum (elems dp)
  30. ݁߹ͷ࢓ํͱঢ়ଶભҠͷؔ਺ ͋ͱॳظঢ়ଶ Λએݴ͢Ε͹ɺ%1͕ղ͚Δ main = do [n, wx] <- getInts

    items <- replicateM n getTuple let dp = accumArrayDP @UArray f max 0 (0, wx) [(0, 0)] items where f (w, acc) (wi, vi) = [(w, acc), (w + wi, acc + vi)] print $ maximum (elems dp)
  31. %1΋ɺந৅Խͨ͠Β݁߹ͱࣸ૾͕ύϥϝʔλԽ͞Εͨ • ࿩ͷྲྀΕతʹೋ࣍ݩ഑ྻ ˠঢ়ଶۭؒͷ৞ΈࠐΈɺͱ͍͏Ϟσϧͷస׵Λઌʹߟ͕͑ͨ • ࣮ࡍʹ͸ɺ%1ͷந৅ԽΛࢼΈͨΒ GPMEͷ࣮૷ʹͳΓɺޙ෇͚ͰҙຯΛߟ͑ͨΒʮঢ়ଶۭؒ ͷ৞ΈࠐΈʯͱ͍͏Ϟσϧʹؾ͕͍ͭͨ • ʮ%1

    ΋ NBQ  SFEVDF GPME.BQ ͡Όͳ͍͔ ʜʯ – ࣸ૾ uuu ঢ়ଶͷભҠ – ݁߹ uuu ෳ਺ܦ࿏͔Βಉ͡ঢ়ଶʹྲྀೖͨ͠ͱ͖ɺ஋ΛҰͭʹू໿ ˞ͨͩ͠ɺ͜ͷϞσϧͰղ͚Δͷ͸φοϓβοΫ%1ɻ֝௓ͼ%1͸͜ͷϞσϧͰ͸ղ͚ͳ͍
  32. ΠϯλϑΣʔεΛோΊΔͱ୅਺తߏ଄΋ݟ͑ͯདྷΔ uuu %1͸൒؀తߏ଄Λ࣋ͭ let dp = accumArrayDP @UArray f (+)

    0 (0, n) [(0, 0)] items f ((v, e) -> x -> [(v, e')]) ঢ়ଶ (v, e) ʹೖྗ x Λ࡞༻ͤ͞ෳ਺ͷભҠઌ (v, e') Λੜ੒͢Δ (࡞༻ తͳ৐๏) (+) (e -> e' -> e) ಉ͡ঢ়ଶʹෳ਺ભҠ͕ू·Δͱ͖ɺ·ͱΊΔ (Ճ๏) 0 e ॳظ஋ (Ճ๏ͷ୯Ґݩ) • %1͸ɺ͋Δঢ়ଶ্ۭؒʹ͓͚ΔϞϊΠυʢࣸ૾ʣ࡞༻ͱɺ൒܈తͳू໿Λ૊Έ߹Θͤͨܭࢉ • GPME.BQ͸.POPJEΛ࢖͏͕ɺͦΕΛΑΓҰൠԽͯ͠4FNJSJOHʹ֦ுͨ͠΋ͷ͕%1Ͱ͋ΔͱΈͳͤ Δ
  33. ந৅ͷߏ଄ ΠϯλϑΣʔε ͕ྑ͘ࣅ͍ͯΔ • #'4΋ %1΋ɺந৅తʹ͸ঢ়ଶۭؒʹ஋Λ഑ΓɾूΊΔૢ࡞ͷ্ʹߏங͞ΕͨϞσϧ • #'4΋൒؀తߏ଄ ·ͨ͸ͦͷ֦ு Λ࣋ͭ

     ·ͩͪΌΜͱߟ͑ΒΕ͍ͯ·ͤΜ let dp = accumArrayDP @UArray f (+) 0 (0, n) [(0, 0)] items let dist = bfs f (+) (-1) (0, n) [(1, 0)]
  34. ͠Ό͘ͱΓ๏ • (+) (-) 0 ··· ݁߹ɺٯݩɺ୯Ґݩ → Մ׵ϞϊΠυ •

    ʮՄ׵ϞϊΠυ্ͷ෦෼۠ؒͷྦྷੵ஋ʯʹରͯ͠ʮ৚݅ f Λຬͨ͢࠷େ۠ؒΛ୳ࡧ͢Δʯ – f ··· ϞϊΠυͷ৞ΈࠐΈʹରͯ͠൑ఆΛ෇͚ͨʮ৚݅෇͖ࣸ૾ʯ let secs = shakutori f (+) (-) 0 as
  35. )BTLFMM͸࠶ؼతσʔλߏ଄Λσʔλߏ଄ͷجຊͱ͍ͯ͠Δ data List a = Nil | Cons a (List

    a) • )BTLFMMͷσʔλߏ଄ uuu ୅਺తσʔλܕʹΑΔ࠶ؼతσʔλߏ଄ • ࠶ؼతσʔλߏ଄ʹదͨ͠࠷খͷૢ࡞͕ NBQͱ SFEVDF GPME – NBQ͸ a -> b Λ֤ཁૉʹద༻͠ɺߏ଄Λอͬͨ··ม׵ ࠶ؼߏ଄ʹର͢Δؔ਺ద༻ͷ࠷খ୯Ґ – SFEVDF GPME ͸ͦͷߏ଄Λյ͠ͳ͕ΒҰͭͷ஋ʹ৞ΈࠐΉ ߏ଄ΛͨͨΉ࠶ؼతύλʔϯͷ࠷খ୯Ґ
  36. ʮࣸ૾ͱ৞ΈࠐΈʯ͸Ͳ͔͜Βདྷͨͷ͔ • -JTQ ʙ ͕Ϧετʹର͢Δ NBQSFEVDFͰɺଟ͘ͷ໰୊Λهड़Ͱ͖Δ͜ͱΛܦݧ తʹൃݟͨ͠ • ؔ਺ܕݴޠͷൃలʹΑΓɺNBQSFEVDF GPME

    ͸ϦετʹݶΒͳ͍࠶ؼతσʔλߏ଄ʹద ͨ͠ૢ࡞Ͱ͋ΔͱҰൠԽ͞Εͨ • )BTLFMM ʙ ͸ͦΕΒΛཧ࿦͚ͮͯ࠶ߏ੒͠ɺܕΫϥε֊૚ͱͱ΋ʹऔΓࠐΜͩ • 'VODUPS 'PMEBCMF "QQMJDBUJWF .POBE 5SBWFSTBCMF • NBQSFEVDF GPME ͸ )BTLFMMͷʮ࠶ؼʯͱʮߏ଄ԽʯΛ؏֩͘ɺݴޠઃܭͷத৺ʹ͋Δ
  37. )BTLFMMͷෆมͳσʔλߏ଄͸ NBQSFEVDF GPME Ͱૢ࡞͢Δ • Ϧετɺ4FUɺ.BQɺ"SSBZ ͳͲͷෆมσʔλߏ଄͸͍ͣΕ΋ 'PMEBCMFɻ·ͨ 'VODUPSͰ ͋ͬͨΓɺͦ͏Ͱͳͯ͘΋

    NBQΛ͍࣋ͬͯΔ • ͦΕΒΛجૅʹΞϧΰϦζϜΛ࣮૷͠ɺ۩ମΛύϥϝʔλԽ͍ͯ͘͠ͱࣗવͱ NBQ΍ GPME ΁ͷҾ਺͕ύϥϝʔλͱͯ͠දΕΔ ͜Ε͕ΞϧΰϦζϜͷந৅ʹG΍ ͷΑ͏ͳؔ਺͕͍ͭ΋දΕΔཧ༝ ӬଓσʔλϓϩάϥϛϯάΛࢤ޲ͨ͠৔߹ͷඞવ ˞ඞͣ͠΋͜ͷߏ଄ʹԊΘͳ͍ΞϧΰϦζϜ΍σʔλߏ଄΋ɺ΋ͪΖΜ͋Γ·͢
  38. ͳͥͦΕ͕ɺ୅਺తߏ଄ͱ݁ͼͭ͘ͷ͔ • લड़ͷ௨Γ ࠶ؼతσʔλߏ଄͸ࣸ૾ͱ݁߹ʹࣗવʹؐݩͰ͖Δ • ঢ়ଶͷʮ఻ൖʯͱʮू໿ʯ͸୅਺తੑ࣭Λඞཁͱ͢Δ – ʮ఻ൖʯ֤ঢ়ଶΛ৽͍͠ঢ়ଶʹࣸ͢ ˠࣸ૾ –

    ʮू໿ʯෳ਺ͷ݁ՌΛҰͭʹ·ͱΊΔ ˠ݁߹ – ͜Ε͕݁߹తͰͳ͚Ε͹࠶ؼɾޮ཰Խ͕೉͍͠ ˠ୅਺తߏ଄ͷཁ੥ ΞϧΰϦζϜΛந৅Խ͢Δͱࣸ૾ͱ݁߹͕ܭࢉͷຊ࣭తͳߏ੒ཁૉͱͯ͠ݱΕΔ ঢ়ଶۭؒΛू߹ͱΈͳ͢ͱɺ୅਺తߏ଄ʢ'VODUPS .POPJE 4FNJSJOHʣʹରԠ͢Δ )BTLFMMͷܕͱߴ֊ؔ਺͸ɺͦͷߏ଄ΛࣗવʹΠϯλϑΣʔεͱͯ͠࿐ग़ͤ͞Δ ந৅Խ͸ʮܭࢉͷ୅਺ʯΛՄࢹԽ͢ΔաఔͰ΋͋Δ
  39. for (int j = 0; j <= W; ++j) dp[0][j]

    = 0; for (int i = 0; i < N; ++i) { for (int j = 0; j <= W; ++j) { if (j >= w[i]) dp[i+1][j] = max(dp[i][j-w[i]] + v[i], dp[i][j]); else dp[i+1][j] = dp[i][j]; } } cout << dp[N][W] << endl;
  40. ؔ਺ܕͰΞϧΰϦζϜΛॻ͘ͱ͖ uuuʮԿΛҙຯ͍ͯ͠Δ͔ʯ • ؔ৺͸ʮߏ଄ʯ΍ʮҙຯʯʹ޲͘ – ˠ͜ͷ NBQ͸ԿΛ͍ࣸͯ͠Δ ͜ͷ GPME͸ͲΜͳԋࢉΛू໿͍ͯ͠Δ •

    ܭࢉ͸ෆมͳσʔλߏ଄ʹର͢Δࣸ૾ͱ৞ΈࠐΈͱͯ͠ߏ੒͞ΕΔ • ΞϧΰϦζϜ͸ࣸ૾ͱ݁߹ͷ૊Έ͋Θͤͱͯ͠هड़͞ΕΔࣜ 🧠ࢥߟ͸ʮߏ଄ͱҙຯʯʹԊͬͯਐΉɻࣜͷߏ੒ΛோΊͯશମ૾Λଊ͑Δɻߏ଄ࢤ޲ɺؔ܎ʹॏ͖Λஔ͘ࢥߟɻ ܭࢉΛྲྀΕͱͯ͠௥͏ͷͰ͸ͳ͘ɺҙຯͷ͋Δߏ੒ NBQ GPME ؔ਺߹੒ ͱͯ͠ଊ͑Δɻ Ұ࿈ͷૢ࡞ΛʮԿΛ͔ͨ͠ʯͰ͸ͳ͘ɺʮͲͷΑ͏ͳҙຯͷ͋Δࣸ૾΍݁߹Λఆ͍ٛͯ͠Δ͔ʯͱݟΔ
  41. let dp = accumArrayDP @UArray f max 0 (0, wx)

    [(0, 0)] items where f (w, acc) (wi, vi) = [(w, acc), (w + wi, acc + vi)] print $ maximum (elems dp)
  42. ந৅Խָ͕͍͠ͷ͸Θ͔͚ͬͨͲɺڝϓϩΛ )BTLFMMͰ΍ΔϝϦοτ͸ • ͋Γ·͢ΑͰ΋ͦΜͳ͜ͱͲ͏Ͱ΋͍͍͡Όͳ͍Ͱ͔͢ɻϩϚϯͰ͢ – ϝϦοτϝϦοτ͏ΔͤʔΜͩΑ – )BTLFMMͰղ͚ͳ͍໰୊ʹग़ձͬͨ͜ͱ͸ͳ͍ – ʮ)BTLFMMʹΑΔந৅͕ิॿྠʹͳΔʯ͜Ε͚ͩͰ΋े෼ͳϝϦοτ

    • ΑΓ۩ମతͳϝϦοτ͸ྫ͑͹uuu – )BTLFMMͷ࠶ؼσʔλܕ Ӭଓσʔλߏ଄ ˠ Ӭଓσʔλߏ଄Λલఏʹͨ͠໰୊ͷ෼ղ – ʮӬଓσʔλϓϩάϥϛϯάͱڝٕϓϩάϥϛϯά ʙ )BTLFMMͰ͕Μ͹Δڝϓϩʯ • IUUQT[FOOEFWOBPZB@JUPBSUJDMFTBCEDBBBC
  43. ࿩ͨ͜͠ͱ • )BTLFMM ͰڝٕϓϩάϥϛϯάʹࢀՃ͍ͯ͠ΔɻΞϧΰϦζϜΛந৅Խ͢Δͱɺͦͷ࣮૷͕ ࣅͨΑ͏ͳΠϯλϑΣʔεʹͳΔ͜ͱΛܦݧͨ͠ – ߴ֊ؔ਺ͱͯࣸ͠૾ Gͱ݁߹ͷೋ߲ԋࢉ͕ύϥϝʔλͱͯ͠Α͘දΕΔ • ͦΕ͸ۮવͳͷ͔ɺ͍΍ɺۮવͰ͸ͳ͍

    – )BTLFMMͷࠜఈʹ͋Δ࠶ؼσʔλߏ଄ɺͦΕʹ࠷దͳૢ࡞Ͱ͋Δࣸ૾ͱ৞ΈࠐΈ NBQSFEVDF • ࣸ૾ͱ৞ΈࠐΈʹΑΔؔ਺ͷΠϯλϑΣʔε͔ΒΞϧΰϦζϜͷ୅਺తߏ଄͕ݟ͑Δ • ؔ਺ܕϓϩάϥϛϯάɺ)BTLFMM͸ΞϧΰϦζϜΛΑΓந৅౓ߴ͘ଊ͑ΔࢥߟΛิॿͯ͘͠ ΕΔ
  44. NJTD • ෆมͳσʔλߏ଄ͱ NBQSFEVDFͰશ෦͍͚Δͷ – ͍͍͑ɻύϑΥʔϚϯεͷ؍఺͔Β .VUBCMF"SSBZ͕ඞཁͳ৔໘͸͋Γ·͢ • 6OJPO'JOEɺηάϝϯτ໦ɺ஗ԆධՁηάϝϯτ໦ͳͲͷ࣮૷ –

    .VUBCMF"SSBZͷૢ࡞΋Ϟφυͷݟ஍͔ΒݟΕ͹ NBQSFEVDFతͳ΋ͷͱͯ͠ଊ͑Δ͜ͱ͸Ͱ ͖Δ͕ɺͦΕΛѻ͏ਓؒͷϝϯλϧϞσϧͱͯ͠͸໋ྩܕతͳૢ࡞ – .VUBCMF"SSBZ͸ඇ࠶ؼతͳݻఆαΠζͷઢܗߏ଄Ͱ͋Γɺ୅਺తσʔλܕͰએݴ͞ΕΔ࠶ؼత σʔλߏ଄ͱ͸ҟͳΔ΋ͷ • ೖग़ྗ΍ཚ਺ಉ༷ͷɺ֎ք 3FBM8PSME ͷӨڹԼʹ͋Δ෭࡞༻తͳଘࡏ ֎෦ࢿݯ ϝϞϦ ͱͷڮ౉͠૷ஔ • .POPJEͱ͔ 4FNJHSPVQͱ͔ͷܕ࢖࣮ͬͯ૷͠ͳ͍ͷ – ࢲ͸࢖ͬͯ·ͤΜ͕ɺ࢖ͬͯ៉ྷͳந৅Λ࣮૷͍ͯ͠Δ "U$PEFSͷઌഐํ΋͍·͢ – ࢲ͸׳Εͱهड़ͷָ͞Λ༏ઌ͍ͯ͠·͢