Here is another slightly different way of phrasing what dynamic programming gives you. Dynamic programming collapses an exponential number of candidate solutions into a polynomial number of equivalence classes, such that the candidate solutions in each class are indistinguishable in some sense.
Let me take as an example the problem of finding the number of increasing subsequences of length k in an array A of lenght n.
It is useful to partition the set of all subsequences into equivalence classes such that two subsequences belong to the same class if and only if they have the same length and end in the same index. All of the 2n possible subsequences belong to exactly one of the O(n2) equivalence classes. This partitioning preserves enough information so that we can define a recurrence relation for the sizes of the classes. If f(i,ℓ) gives the number of subsequences which end in index i and have length ℓ, then we have:
f(i,ℓ)=∑j<i such thatA[j]<A[i]f(j,ℓ−1)
f(i,1)=1 for all i=1…n
This recurrence solves the problem in time O(n2k).