[Knapsack problem][1] is $\sf{NP\text{-}complete}$ when the numbers are given as *binary* numbers. In this case, the dynamic programming will take exponentially many steps (in the size of the input, i.e. the number of bits in the input) to finish $\dagger$. 

On the other hand, if the numbers in the input are given in unary, the dynamic programming will work in polynomial time (in the size of the input).

This kind of problems is called [weakly $\sf{NP\text{-}complete}$][2].


$\dagger$: Another good example to understand the importance of the encoding used to give the input is considering the usual algorithms to see if a number is prime that go from $2$ up to $\sqrt{n}$ and check if any of them divide $n$. This is polynomial in $n$ but not necessarily in the input size. If $n$ is given in binary, the size of input is $\lg n$ and the algorithm runs in time $O(\sqrt{n}) = O(2^{\lg n/2})$ which is exponential in the input size. And the usual computational complexity of a problem is w.r.t. the size of the input.

This kind of algorithm, i.e. polynomial in the largest number that is part of the input, but exponential in the input length is called [*pseudo-polynomial*](https://en.wikipedia.org/wiki/Pseudo-polynomial_time).

  [1]: http://en.wikipedia.org/wiki/Knapsack_problem
  [2]: http://en.wikipedia.org/wiki/Weakly_NP-complete