【问题标题】:Making change with minimum denominations with memoization通过记忆化以最小面额进行更改
【发布时间】:2018-03-25 08:09:17
【问题描述】:

我想知道如何通过记忆来制作高效的算法。特别是,有没有办法让 Haskell 中索引值的访问时间为 O(1)?

这里是the problem described in detail。这是我对递归算法的尝试:

denom :: (Int, Int) -> [Int] -> Int
denom (_, 0) _ = 0
denom (0, _) _ = (maxBound :: Int) - 1000 -- subtracting 1000 otherwise overflows
denom (i, j) di
  | v > j = denom (i-1, j) di
  | otherwise = min (denom (i-1, j) di) (1 + denom (i, j-v) di)
  where v = di !! (i - 1)

另外,我将如何在 Haskell 中声明 INFINITY 以便 min 在所有情况下都有效?

【问题讨论】:

  • 你可以通过使用数组而不是列表来获得 O(1) !
  • 如果您不想自己编写备忘录,则存在helper libraries

标签: haskell dynamic-programming memoization


【解决方案1】:

首先,要在 Haskell 中访问 O(1),标准的首选库是 Data.Array

其次,定义一个类型附近但不知何故“外部”的东西的一般方法是使用Maybe类型;这是我对INFINITY 的推荐。另外,我认为这在算法中更有意义,因为INFINITY 真正的意思是“我们不能用这套面额来做这个值”,而不是“我们可以用无限数量的硬币来做这个值”。

因此,使用Maybe,我们首先要定义的是在Maybe Int 上工作的min 版本:

myMin :: Ord a => Maybe a -> Maybe a -> Maybe a
myMin (Just a) (Just b) = Just $ min a b
myMin Nothing x = x
myMin x Nothing = x

然后,我们可以使用链接页面中给出的算法来解决这个问题:

minCoinCoint :: Int -> [Int] -> Maybe Int
minCoinCoint target denoms = res (target, length denoms)
  where
    denomArray = listArray (0, length denoms) (0:denoms)
    myArrayBounds = ((0, 0), (target, length denoms))
    myArray = array myArrayBounds [(i, res i) | i <- range myArrayBounds]
    res (_, 0) = Nothing
    res (0, _) = Just 0
    res (t, d) = let dval = denomArray ! d
                     prev1 = myArray ! (t, d-1)
                     prev2 = if t >= dval
                             then (+1) <$> (myArray ! (t-dval, d))
                             else Nothing
                 in myMin prev1 prev2

就是这样。 (好吧,假设你记得文件顶部的 import Data.Array 行)

请注意,myArray 是通过引用 res 构建的,res 通过在 myArray 中查找值来进行所有递归调用。

这个语法可能有点混乱:

(+1) <$> (myArray ! (t-dval, d))

这样做是因为请记住myArray 的每个元素不是Int,而是Maybe Int。该语法表示“将函数 (+1) 应用于值 (myArray ! (t-dval, d)) 的内部”,因此 Just 4 将变为 Just 5,但 Nothing 仍将是 Nothing

【讨论】:

  • 我意识到我从显示的页面交换了参数的顺序(t, d)。除非人们真的觉得它令人困惑,否则我不会回去修复它。
猜你喜欢
  • 2021-02-10
  • 2021-02-21
  • 2020-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多