public StolenItems FindKnackSnapMaxValueWithItems(int capacity, int[] weights, int[] values, int n)
        {
            //base case
            if (n == values.Length || capacity == 0)
            {
                StolenItems item = new StolenItems();
                item.Max   = 0;
                item.Items = string.Empty;
                return(item);
            }

            if (weights[n] > capacity)
            {
                //if the current n weight is greater than the capacity, skip n and go for next
                return(FindKnackSnapMaxValueWithItems(capacity, weights, values, n + 1));
            }

            //Get the max value excluding the current for the weight of capacity
            StolenItems excludeitem = FindKnackSnapMaxValueWithItems(capacity, weights, values, n + 1);

            //Get the max value including the current for the weight of capacity
            //since we are includeitem = new StolenItems();
            StolenItems includeitem = new StolenItems();

            includeitem     = FindKnackSnapMaxValueWithItems(capacity - weights[n], weights, values, n + 1);
            includeitem.Max = values[n] + includeitem.Max;



            StolenItems currentitem = new StolenItems();

            //return the max of the including or excluding

            if (excludeitem.Max > includeitem.Max)
            {
                currentitem.Items = excludeitem.Items;
                currentitem.Max   = excludeitem.Max;
            }
            else
            {
                currentitem.Items = includeitem.Items + " , " + values[n];
                currentitem.Max   = includeitem.Max;
            }
            return(currentitem);
        }
        //Logic of this Dynamic Program
        //We iterate for each unit of the weight againt each item
        //As usual put the first row and column as zero (if there is no weight we can't put any item or if there is no item, there is no value)
        //If the item cannot be put into the bag of the weight(w), then put zero
        //if the item can fit into bag then take two values
        //value1  - one the cell about it cell[row -1, col]
        //and value2 - value of the item + (if there are any weight left, then find the left unit for this item and get the value from the row above row  m[row -1, [weightleft]
        //set max of value1 and value2
        //continue till last
        //last bottom right will be the answer and that is the maxvalue for using all weight and for all items

        //create an another array to keep track of all the matches- this will be used to backtrack the items
        //with the backtrack array you can check whether each item is added. It a item is added subtract it's weight and check the next item for the remaining weight

        //https://www.youtube.com/watch?v=EH6h7WA7sDw
        public StolenItems FindKnackSnapMaxValueWithItemsUsingDP(int[] weight, int[] values, int capacity)
        {
            //Declare an array with one index greater than given
            //Let's m the x-axia as weight and y axis as value
            int noofitems = weight.Length;

            int[,] maxarray  = new int[noofitems + 1, capacity + 1];
            int[,] backtrack = new int[noofitems + 1, capacity + 1];

            // Build table K[][] in bottom up manner
            //noofitem = value.Length...not index
            //iterate for ech item
            for (int i = 0; i <= noofitems; i++)
            {
                //each unit of weight
                for (int j = 0; j <= capacity; j++)
                {
                    if (i == 0 || j == 0)
                    {
                        maxarray[i, j] = 0;
                    }
                    //check the item can fit into the bag of capacity j
                    //int[] weight is index based and we are iterating via length based
                    else if (weight[i - 1] <= j)
                    {
                        //it can fit into the bag
                        int value1 = maxarray[i - 1, j];
                        int value2 = values[i - 1] + maxarray[i - 1, (j - weight[i - 1])];
                        maxarray[i, j] = Math.Max(value1, value2);

                        //logic for backtrack array..
                        //if the item is placed in the bag then mark 1 else 0 ( by default it is zero)
                        if (maxarray[i, j] == value2) //which means this is placed in the bag
                        {
                            backtrack[i, j] = 1;
                        }
                    }
                    else
                    {
                        //cannot fit
                        maxarray[i, j] = 0;
                    }
                }
            }

            StolenItems items = new StolenItems();

            items.Max = maxarray[noofitems, capacity];

            //We need to find the items
            //keep track of remaining capacity in the bag
            int w = capacity;

            bool[] itemsused = new bool[noofitems];

            //check whether each item can be added from last item
            //i = 3,2,1
            for (int i = noofitems; i > 0; i--)
            {
                if (backtrack[i, w] == 1)
                {
                    //we are keeping this item in the bag
                    itemsused[i - 1] = true;
                    //substract actual weight of the item
                    // w = w - 1;
                    w = w - weight[i - 1];
                }
                else
                {
                    itemsused[i - 1] = false;
                }
            }

            StringBuilder sb = new StringBuilder();

            for (int k = 0; k < itemsused.Length; k++)
            {
                if (itemsused[k])
                {
                    sb.Append(values[k]).Append(",");
                }
            }


            //test this logic use this logic in real world

            StringBuilder sb2 = new StringBuilder();
            //values will be 0,1,2
            int runningcapacity = capacity;

            for (int j = 0; j < values.Length; j++)
            {
                //backtrack array has one extra item so the corresponding value will be j + 1

                if (backtrack[j + 1, runningcapacity] == 1)
                {
                    sb2.Append(values[j]).Append(",");
                    runningcapacity = runningcapacity - weight[j];
                }
            }

            //check sb is equal to sb2
            bool test = sb2.Equals(sb);


            items.Items = sb.ToString();


            return(items);
        }