input: Write a function to solve a knapsack problem using dynamic programming. The function should take in the list of items with their values and weights, and the capacity of the knapsack. The function should return the maximum value that can be put in the knapsack without exceeding the capacity. If the list of items is empty, the function should return 0.
  
  def knapSack(W, wt, val, n):
    
      # Base Case 
      if n == 0 or W == 0 : 
          return 0
    
      # If weight of the nth item is more 
      # than Knapsack capacity W, then 
      # this item cannot be included in the optimal solution 
      if (wt[n-1] > W): 
          return knapSack(W, wt, val, n-1) 
    
      # return the maximum of two cases: 
      # (1) nth item included 
      # (2) not included 
      else: 
          return max(val[n-1] + knapSack(W-wt[n-1], wt, val, n-1), 
                      knapSack(W, wt, val, n-1)) 
    
  # end of function knapSack
  
  assert knapSack(50, [10, 20, 30], [60, 100, 120], 3) == 220
  assert knapSack(40, [10, 20, 30], [60, 100, 120], 3) == 160
  assert knapSack(0, [10, 20, 30], [60, 100, 120], 3) == 0
  assert knapSack(50, [], [], 0) == 0
  assert knapSack(10, [5, 5, 5], [30, 30, 30], 3) == 60
output: def knapSack(W, wt, val, n):
      dp = [[0 for _ in range(W + 1)] for _ in range(n + 1)]
      
      for i in range(1, n + 1):
          for w in range(1, W + 1):
              if wt[i-1] <= w:
                  dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w])
              else:
                  dp[i][w] = dp[i-1][w]
      
      return dp[n][W]