Task: Knapsack problem_Bounded



C#: using System;  
class program
{
    static void Main()
    {
        knapSack(40);
        var sw = System.Diagnostics.Stopwatch.StartNew();
        Console.Write(knapSack(400) + "\n" + sw.Elapsed);  
        Console.Read();
    }

    static string knapSack(uint w1)
    {
        init(); change();
        uint n = (uint)w.Length; var K = new uint[n + 1, w1 + 1];
        for (uint vi, wi, w0, x, i = 0; i < n; i++)
            for (vi = v[i], wi = w[i], w0 = 1; w0 <= w1; w0++)
            {
                x = K[i, w0];
                if (wi <= w0) x = max(vi + K[i, w0 - wi], x);
                K[i + 1, w0] = x;
            }
        string str = "";
        for (uint v1 = K[n, w1]; v1 > 0; n--)
            if (v1 != K[n - 1, w1])
            {
                v1 -= v[n - 1]; w1 -= w[n - 1]; str += items[n - 1] + "\n";
            }
        return str;
    }

    static uint max(uint a, uint b) { return a > b ? a : b; }

    static byte[] w, v; static string[] items;

    static byte[] p = { 1, 1, 2, 2, 2, 3, 3, 3, 1, 3, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 2 };

    static void init()
    {
        w = new byte[] { 9, 13, 153, 50, 15, 68, 27, 39, 23, 52, 11,
                          32, 24, 48, 73, 42, 43, 22, 7, 18, 4, 30 };

        v = new byte[] { 150, 35, 200, 60, 60, 45, 60, 40, 30, 10, 70,
                          30, 15, 10, 40, 70, 75, 80, 20, 12, 50, 10 };

        items = new string[] {"map","compass","water","sandwich","glucose","tin",
                              "banana","apple","cheese","beer","suntan cream",
                              "camera","T-shirt","trousers","umbrella",
                              "waterproof trousers","waterproof overclothes",
                              "note-case","sunglasses","towel","socks","book"};
    }

    static void change()
    {
        int n = w.Length, s = 0, i, j, k; byte xi;
        for (i = 0; i < n; i++) s += p[i];
        {
            byte[] x = new byte[s];
            for (k = i = 0; i < n; i++)
                for (xi = w[i], j = p[i]; j > 0; j--) x[k++] = xi;
            w = x;
        }
        {
            byte[] x = new byte[s];
            for (k = i = 0; i < n; i++)
                for (xi = v[i], j = p[i]; j > 0; j--) x[k++] = xi;
            v = x;
        }
        string[] pItems = new string[s]; string itemI;
        for (k = i = 0; i < n; i++)
            for (itemI = items[i], j = p[i]; j > 0; j--) pItems[k++] = itemI;
        items = pItems;
    }
}





Python: 

import strformat
import tables


type Item = tuple[name: string; weight, value, pieces: int]


const Items: seq[Item] = @[("map", 9, 150, 1),
                           ("compass", 13, 35, 1),
                           ("water", 153, 200, 2),
                           ("sandwich", 50, 60, 2),
                           ("glucose", 15, 60, 2),
                           ("tin", 68, 45, 3),
                           ("banana", 27, 60, 3),
                           ("apple", 39, 40, 3),
                           ("cheese", 23, 30, 1),
                           ("beer", 52, 10, 3),
                           ("suntan cream", 11, 70, 1),
                           ("camera", 32, 30, 1),
                           ("T-shirt", 24, 15, 2),
                           ("trousers", 48, 10, 2),
                           ("umbrella", 73, 40, 1),
                           ("waterproof trousers", 42, 70, 1),
                           ("waterproof overclothes", 43, 75, 1),
                           ("note-case", 22, 80, 1),
                           ("sunglasses", 7, 20, 1),
                           ("towel", 18, 12, 2),
                           ("socks", 4, 50, 1),
                           ("book", 30, 10, 2)
                          ]

type

  
  Number = range[0..Items.high]

  
  ExpandedItem = tuple[num: Number; weight, value: int]




proc expandedItems(items: seq[Item]): seq[ExpandedItem] =
  
  for idx, item in Items:
    for _ in 1..item.pieces:
      result.add((idx.Number, item.weight, item.value))

const ItemList = expandedItems(Items)

type

  
  ExpandedIndex = 0..ItemList.high

  
  Choice = tuple[indexes: set[ExpandedIndex]; weight, value: int]


var cache: Table[tuple[index, weight: int], Choice]




proc select(idx, weightLimit: int): Choice =
  

  if idx < 0 or weightLimit == 0:
    return

  if (idx, weightLimit) in cache:
    return cache[(idx, weightLimit)]

  let weight = ItemList[idx].weight
  if weight > weightLimit:
    return select(idx - 1, weightLimit)

  
  result = select(idx - 1, weightLimit)

  
  var result1 = select(idx - 1, weightLimit - weight)
  inc result1.value, ItemList[idx].value

  
  if result1.value > result.value:
    result = (result1.indexes + {idx.ExpandedIndex}, result1.weight + weight, result1.value)

  cache[(idx, weightLimit)] = result



let (indexes, weight, value) = select(ItemList.high, 400)


var pieces = newSeq[int](Items.len)
for idx in indexes:
  inc pieces[ItemList[idx].num]

echo "List of items:"
for num in 0..Items.high:
  if pieces[num] > 0:
    echo fmt"– {pieces[num]} of {Items[num].pieces} {Items[num].name}"
echo ""
echo "Total weight: ", weight
echo "Total value: ", value