Data Structures, Algorithms, & Applications in Java
Chapter 20, Exercise 3

To compute the xs, we need to save the decisions made when an f is computed. Then following the computation of f(1,c), we can perform a traceback similar to that done in Program 20.3. We save the decisions in a two-dimensional array f.

The modified program together with the traceback method is given below. A test program, input, and output appear in the files RecursiveDPKnapsack2.*.
public class RecursiveDPKnapsack2
{
   static int [] profit;
   static int [] weight;    
   static int numberOfObjects;
   static int [][] d;        // decision array

   /** set class data members and invoke method f 
     * @param theProfit[1:theProfit.length - 1] gives object profits
     * @param theWeight[1:theWeight.length-1] gives object weights
     * @param theD[1:p.length - 1][c+ 1] is array to return decisions in
     * @return value of optimal knapsack filling */
   public static int knapsack(int [] theProfit, int [] theWeight,
                              int knapsackCapacity, int [][] theD)
   {
      profit = theProfit;
      weight = theWeight;
      numberOfObjects = theProfit.length - 1;
      d = theD;
      return f(1, knapsackCapacity);
   }
      
   /** recursive method to solve dynamic programming recurrence
     * @return f(i, theCapacity) */
   private static int f(int i, int theCapacity)
   {
      if (i == numberOfObjects)
         // use Equation 20.1
         if (theCapacity < weight[numberOfObjects])
         {// x[numberOfObjects] is 0
           d[numberOfObjects][theCapacity] = 0;
           return 0;
         }
         else
         {// x[numberOfObjects] is 1
            d[numberOfObjects][theCapacity] = 1;
            return profit[numberOfObjects];
         }
   
      // use Equation 20.2
      if (theCapacity < weight[i])
      {// x[i] is 0
         d[i][theCapacity] = 0;
         return f(i + 1, theCapacity); 
      }
      
      int p0 = f(i + 1, theCapacity);
      int p1 = f(i + 1, theCapacity - weight[i]) + profit[i];
      if (p0 < p1)
      {// x[i] is 1
         d[i][theCapacity] = 1;
         return p1;
      }

      // x[i] is 0
      d[i][theCapacity] = 0;
      return p0;
   }
   
   /** compute x for optimal filling
     * @param theD is decision array
     * @param theWeight[1:theWeight.length-1] gives object weights */
   public static void traceback(int [][] theD, int [] theWeight,
                                int knapsackCapacity, int [] x)
   {
      numberOfObjects = theWeight.length - 1;
      for (int i = 1; i < numberOfObjects; i++)
         if (d[i][knapsackCapacity] == 1)
         {
            x[i] = 1;
            knapsackCapacity -= theWeight[i];
         }
         else
            x[i] = 0;
      x[numberOfObjects] = d[numberOfObjects][knapsackCapacity];
   }
}