Chúng ta đã nhận thấy sức mạnh và tính hiệu quả của phương pháp quy hoạch động. Tuy nhiên không có phương pháp nào là hoàn hảo. Phương pháp quy hoạch động có một số nhược điểm lớn như sau:
1. Không phải bài toán nào cũng giải được bằng quy hoạch động. Hiện nay người ta vẫn chưa tìm được điều kiện cần và đủ để một bài toán có thể giải được bằng phương pháp quy hoạch động. Do đó để xác định được một bài toán có thể giải được bằng quy hoạch động và tìm được công thức quy hoạch động của nó thường là việc rất khó khăn.
2. Nếu bài toán có thể giải được bằng quy hoạch động thì yêu cầu về không gian nhớ
cũng khá lớn. Đa số các bài toán đều có đòi hỏi không gian bộ nhớ cỡ O(n2). Nếu môi
trường lập trình hạn chế bộ nhớ thì sẽ không thể làm việc được với các dữ liệu lớn, mặc dù phương pháp quy hoạch động có độ phức tạp tính toán không cao.
Nhược điểm 1 nhìn chung là khó giải quyết. Chỉ có cách cố gắng đưa bài toán đang xét về một mô hình nào đó đã được chứng minh là làm được bằng quy hoạch động và đã tìm được công thức quy hoạch động. Chẳng hạn: mô hình dãy con đơn điệu tăng dài nhất, xâu con chung, xếp balô, nhân ma trận…
Nhược điểm 2 thì có thể giải quyết dễ dàng hơn. Chú ý vào công thức quy hoạch động, ta thường thấy F[n] thường chỉ phải tính qua F[n-1]. Do đó ta không cần phải lưu trữ cả bảng phương án mà chỉ cần lưu một số vị trí cần thiết. Nếu bài toán có yêu cầu truy vết tìm nghiệm thì ta có thể dùng bảng truy vết có kích thước thường là nhỏ hơn bảng phương án.
Chẳng hạn ta có kỹ thuật sau giải bài toán xâu con chung dài nhất cho 2 xâu có độ dài cỡ 1000. (Chú ý, xâu trong TP chỉ có độ dài tối đa 255 nên trong trường hợp này ta phải dùng mảng kí tự để lưu trữ 2 xâu).
Nhắc lại công thức quy hoạch động của bài toán: 1. L(0,j)=L(i,0)=0.
2. L(i,j) = L(i−1,j−1)+1 nếu X[i] = Y[j].
3. L(i,j) = max(L(i−1,j), L(i,j−1)) nếu X[i] ≠ Y[j].
Như vậy để tính L(i) ta chỉ cần L(i-1). Do đó để tính cả bảng phương án, ta chỉ cần lưu trữ hai dòng của nó: L để lưu L(i) và L1 để lưu L(i-1). Chương trình con quy hoạch động được viết lại như sau:
procedure Optimize; var i,j; begin for j := 0 to n do L1[j] := 0; {L(0,j):=0} for i := 1 to m do begin L[0]:=0; for j := 1 to n do
if X[i]=Y[j] then L[j] := L1[j-1]+1 {L(i,j)=L(i-1,j-1)+1} else
L[j]:=max(L1[j],L[j-1]]); {L(i,j)=max(L(i1,j), L(i,j1))} L1 := L;
end; end;
Nếu chỉ yêu cầu tìm độ dài xâu con chung dài nhất (L[m,n]) thì với cách này ta có thể giải với kích thước m,n=10000 cũng được. Nếu bài toán yêu cầu tìm lại kết quả thì ta phải dùng thêm một bảng truy vết 2 chiều. Khi đó mỗi phần tử của bảng truy vết chỉ cần lưu 1 trong 3 giá trị: T[i,j]=1 nếu L(i,j)=L(i-1,j-1)+1, T[i,j]=2 nếu L(i,j)=L(i-1,j) và T[i,j]=3 nếu L(i,j)=L(i,j-1). Do đó kích thước bảng truy vết nhỏ hơn nhiều so với bảng phương án. (Ta chỉ cần 2 bit cho một phần tử của bảng truy vết nên kích thước bảng truy vết là 1000x1000x2bit=2.000.000 bit, tức là khoảng 250KB. Trong khi đó bảng phương án 2 chiều có kích thước là 1000x1000x2byte=2.000.000 byte, tức là lớn hơn 8 lần).
Chi tiết cài đặt cụ thể, độc giả có thể xem ở phần phụ lục. Kĩ thuật này có thể áp dụng được bài toán xếp balô.