Cho vat pham, vat thu co trong luong va gia tri . Ban co mot ba lo voi suc chua toi da . Hay chon mot tap con cac vat pham sao cho tong trong luong khong vuot qua va tong gia tri la lon nhat.
Rang buoc: moi vat pham chi duoc chon hoac khong chon (0/1), khong duoc chia nho.
Input mau: , , trong luong , gia tri .
Goi la gia tri lon nhat khi xet vat pham dau tien voi suc chua . Ta co cong thuc truy hoi:
Truong hop co so: voi moi (khong chon vat nao thi gia tri bang ).
Dieu kien: chi co the lay vat khi . Neu thi .
Hang tuong ung voi viec khong chon vat nao. Moi o . Cac hang tiep theo se duoc dien bang cach ap dung cong thuc truy hoi, xet tung vat pham mot tu trai sang phai.
Moi o dai dien cho bai toan con: gia tri lon nhat co the dat duoc khi chi xet vat pham dau va suc chua la . Tai moi o, ta co hai lua chon:
Gia tri lon hon trong hai lua chon se duoc ghi vao .
Sau khi dien xong bang DP, dap an nam o . De biet nhung vat nao duoc chon, ta truy vet tu nguoc ve :
Trong vi du tren: (khong lay vat ), (khong lay vat ), (lay vat , giam tu ve ), (lay vat , giam tu ve ). Vay tap vat duoc chon la voi tong gia tri .
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, W;
cin >> n >> W;
vector<int> w(n + 1), v(n + 1);
for (int i = 1; i <= n; i++)
cin >> w[i] >> v[i];
// dp[i][j] = max value using items 1..i with capacity j
vector<vector<int>> dp(n + 1, vector<int>(W + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= W; j++) {
dp[i][j] = dp[i - 1][j]; // skip item i
if (j >= w[i])
dp[i][j] = max(dp[i][j], dp[i - 1][j - w[i]] + v[i]);
}
}
cout << dp[n][W] << "\n";
// Backtrack to find chosen items
vector<int> chosen;
for (int i = n, j = W; i >= 1; i--) {
if (dp[i][j] != dp[i - 1][j]) {
chosen.push_back(i);
j -= w[i];
}
}
reverse(chosen.begin(), chosen.end());
for (int x : chosen)
cout << x << " ";
cout << "\n";
return 0;
}
Do phuc tap: thoi gian va bo nho. Co the toi uu bo nho xuong bang cach chi giu mot hang DP va duyet giam dan.