code: def knapsack(p, v, cmax):
      
      n = len(p)
      opt = [[0] * (cmax + 1) for _ in range(n + 1)]
      sel = [[False] * (cmax + 1) for _ in range(n + 1)]
      #                               --- basic case
      for cap in range(p[0], cmax + 1):
          opt[0][cap] = v[0]
          sel[0][cap] = True
      #                               --- induction case
      for i in range(1, n):
          for cap in range(cmax + 1):
              if cap >= p[i] and opt[i-1][cap - p[i]] + v[i] > opt[i-1][cap]:
                  opt[i][cap] = opt[i-1][cap - p[i]] + v[i]
                  sel[i][cap] = True
              else:
                  opt[i][cap] = opt[i-1][cap]
                  sel[i][cap] = False
      #                               --- reading solution
      cap = cmax
      solution = []
      for i in range(n-1, -1, -1):
          if sel[i][cap]:
              solution.append(i)
              cap -= p[i]
      return (opt[n - 1][cmax], solution)
docs: Knapsack problem: select maximum value set of items if total size not more than capacity
  
      :param p: table with size of items
      :param v: table with value of items
      :param cmax: capacity of bag
      :requires: number of items non-zero
      :returns: value optimal solution, list of item indexes in solution
      :complexity: O(n * cmax), for n = number of items