Task: Knapsack problem_0-1








VB: 
Option Explicit
Const maxWeight = 400
Dim DataList As Variant
Dim xList(64, 3) As Variant
Dim nItems As Integer
Dim s As String, xss As String
Dim xwei As Integer, xval As Integer, nn As Integer

Sub Main()
    Dim i As Integer, j As Integer
    DataList = Array("map", 9, 150, "compass", 13, 35, "water", 153, 200, "sandwich", 50, 160, _
           "glucose", 15, 60, "tin", 68, 45, "banana", 27, 60, "apple", 39, 40, _
           "cheese", 23, 30, "beer", 52, 10, "suntan cream", 11, 70, "camera", 32, 30, _
           "T-shirt", 24, 15, "trousers", 48, 10, "umbrella", 73, 40, "book", 30, 10, _
           "waterproof trousers", 42, 70, "waterproof overclothes", 43, 75, _
           "note-case", 22, 80, "sunglasses", 7, 20, "towel", 18, 12, "socks", 4, 50)
    nItems = (UBound(DataList) + 1) / 3
    j = 0
    For i = 1 To nItems
        xList(i, 1) = DataList(j)
        xList(i, 2) = DataList(j + 1)
        xList(i, 3) = DataList(j + 2)
        j = j + 3
    Next i
    s = ""
    For i = 1 To nItems
        s = s & Chr(i)
    Next
    nn = 0
    Call ChoiceBin(1, "")
    For i = 1 To Len(xss)
        j = Asc(Mid(xss, i, 1))
        Debug.Print xList(j, 1)
    Next i
    Debug.Print "count=" & Len(xss), "weight=" & xwei, "value=" & xval
End Sub 

Private Sub ChoiceBin(n As String, ss As String)
    Dim r As String
    Dim i As Integer, j As Integer, iwei As Integer, ival As Integer
    Dim ipct As Integer
    If n = Len(s) + 1 Then
        iwei = 0: ival = 0
        For i = 1 To Len(ss)
            j = Asc(Mid(ss, i, 1))
            iwei = iwei + xList(j, 2)
            ival = ival + xList(j, 3)
        Next
        If iwei <= maxWeight And ival > xval Then
            xss = ss: xwei = iwei: xval = ival
        End If
    Else
        r = Mid(s, n, 1)
        Call ChoiceBin(n + 1, ss & r)
        Call ChoiceBin(n + 1, ss)
    End If
End Sub 




Ada: with Ada.Text_IO;
with Ada.Strings.Unbounded;

procedure Knapsack_01 is
   package US renames Ada.Strings.Unbounded;

   type Item is record
      Name   : US.Unbounded_String;
      Weight : Positive;
      Value  : Positive;
      Taken  : Boolean;
   end record;

   type Item_Array is array (Positive range <>) of Item;

   function Total_Weight (Items : Item_Array; Untaken : Boolean := False) return Natural is
      Sum : Natural := 0;
   begin
      for I in Items'Range loop
         if Untaken or else Items (I).Taken then
            Sum := Sum + Items (I).Weight;
         end if;
      end loop;
      return Sum;
   end Total_Weight;

   function Total_Value (Items : Item_Array; Untaken : Boolean := False) return Natural is
      Sum : Natural := 0;
   begin
      for I in Items'Range loop
         if Untaken or else Items (I).Taken then
            Sum := Sum + Items (I).Value;
         end if;
      end loop;
      return Sum;
   end Total_Value;

   function Max (Left, Right : Natural) return Natural is
   begin
      if Right > Left then
         return Right;
      else
         return Left;
      end if;
   end Max;

   procedure Solve_Knapsack_01 (Items : in out Item_Array;
                                Weight_Limit : Positive := 400) is
      type W_Array is array (0..Items'Length, 0..Weight_Limit) of Natural;
      W : W_Array := (others => (others => 0));
   begin
      
      for I in Items'Range loop
         for J in 1 .. Weight_Limit loop
            if Items (I).Weight > J then
               W (I, J) := W (I - 1, J);
            else
               W (I, J) := Max (W (I - 1, J),
                                W (I - 1, J - Items (I).Weight) + Items (I).Value);
            end if;
         end loop;
      end loop;
      declare
         Rest : Natural := Weight_Limit;
      begin
         for I in reverse Items'Range loop
            if W (I, Rest) /= W (I - 1, Rest) then
               Items (I).Taken := True;
               Rest := Rest - Items (I).Weight;
            end if;
         end loop;
      end;
   end Solve_Knapsack_01;

   All_Items : Item_Array :=
     ( (US.To_Unbounded_String ("map"),                      9, 150, False),
       (US.To_Unbounded_String ("compass"),                 13,  35, False),
       (US.To_Unbounded_String ("water"),                  153, 200, False),
       (US.To_Unbounded_String ("sandwich"),                50, 160, False),
       (US.To_Unbounded_String ("glucose"),                 15,  60, False),
       (US.To_Unbounded_String ("tin"),                     68,  45, False),
       (US.To_Unbounded_String ("banana"),                  27,  60, False),
       (US.To_Unbounded_String ("apple"),                   39,  40, False),
       (US.To_Unbounded_String ("cheese"),                  23,  30, False),
       (US.To_Unbounded_String ("beer"),                    52,  10, False),
       (US.To_Unbounded_String ("suntan cream"),            11,  70, False),
       (US.To_Unbounded_String ("camera"),                  32,  30, False),
       (US.To_Unbounded_String ("t-shirt"),                 24,  15, False),
       (US.To_Unbounded_String ("trousers"),                48,  10, False),
       (US.To_Unbounded_String ("umbrella"),                73,  40, False),
       (US.To_Unbounded_String ("waterproof trousers"),     42,  70, False),
       (US.To_Unbounded_String ("waterproof overclothes"),  43,  75, False),
       (US.To_Unbounded_String ("note-case"),               22,  80, False),
       (US.To_Unbounded_String ("sunglasses"),               7,  20, False),
       (US.To_Unbounded_String ("towel"),                   18,  12, False),
       (US.To_Unbounded_String ("socks"),                    4,  50, False),
       (US.To_Unbounded_String ("book"),                    30,  10, False) );

begin
   Solve_Knapsack_01 (All_Items, 400);
   Ada.Text_IO.Put_Line ("Total Weight: " & Natural'Image (Total_Weight (All_Items)));
   Ada.Text_IO.Put_Line ("Total Value:  " & Natural'Image (Total_Value  (All_Items)));
   Ada.Text_IO.Put_Line ("Items:");
   for I in All_Items'Range loop
      if All_Items (I).Taken then
         Ada.Text_IO.Put_Line ("   " & US.To_String (All_Items (I).Name));
      end if;
   end loop;
end Knapsack_01;