私は Knapsack で遊んでおり (正当な理由はなく、錆を取り除こうとしているだけです)、お気に入りの言語で実装したいと考えていました。
(笑わないでください。大学を卒業してからしばらく経ちます。私は Scala の初心者です)
これが私の最初の実行です(正しいソリューションが返されますが、最適とはほど遠いと思います):
import scala.collection.mutable.HashMap
object Main {
  def main(args: Array[String]) {
    val weights = List(23, 31, 29, 44, 53, 38, 63, 85, 89, 82)
    val values = List(92, 57, 49, 68, 60, 43, 67, 84, 87, 72)
    val wv = weights zip values
    val solver = new KnapSackSolver()
    solver.solve(wv, 165) 
  }
  class KnapSackSolver() {
    var numberOfIterations = 0
    type Item = (Int, Int)
    type Items = List[Item]
    val cache = new HashMap[(Items, Int), Items]()
    def sackValue(s: Items) = if (s.isEmpty) 0 else s.map(_._2).sum
    def solve(wv: Items, capacity: Int) = {
      numberOfIterations = 0
      val solution = knapsack(wv, capacity)
      println(s"""|Solution: $solution
                  |Value: ${sackValue(solution)}
                  |Number of iterations: $numberOfIterations
      """.stripMargin)
      solution 
    }
    private[this] def knapsack(wv: Items, capacity: Int): Items = {
      numberOfIterations +=1
      val cacheKey = (wv, capacity)
      if (cache.contains(cacheKey)) {
        return cache(cacheKey) //I know, I wrote a return, just wanted an early exit
      }
      if (capacity <= 0 || wv.isEmpty) {
        Nil
      } else if (wv.head._1 > capacity) {
        knapsack(wv.tail, capacity)
      } else {
        val sackNotTakingCurrent = knapsack(wv.tail, capacity)
        val sackTakingCurrent = knapsack(wv.tail, capacity - wv.head._1) :+ wv.head
        val notTakingCurrentValue = sackValue(sackNotTakingCurrent)
        val takingCurrentValue = sackValue(sackTakingCurrent)
        val ret =
          if (notTakingCurrentValue >= takingCurrentValue) sackNotTakingCurrent
          else sackTakingCurrent
        cache(cacheKey) = ret
        ret
      }
    }
  }
}
質問
私の素朴な「キャッシング」は十分ではないようです(565回対534回の繰り返し)が、それを改善する方法がわかりません。
言い換えれば、これは最適な解決策ですか? 私には非常に指数関数的に感じますが、疑似多項式が実際に何を意味するのかを理解していると言ったら嘘をつきます.