Dynamic Programming Practice: 0-1 Knapsack and Weight Measurement Problems
The 0-1 knapsack problem serves as a foundational dynamic programming challenge. Given a time limit t and m herbs, each with a collection time and value, the goal is to maximize total value without exceeding the time limit. The solution uses a 2D DP table where dp[i][j] represents the maximum value achievable using the first i items within time j. For each item, if its time cost exceeds the current capacity, its skipped; otherwise, the algorithm chooses between including or excluding it based on which yields higher value.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t, m;
cin >> t >> m;
vector<int> time(m + 1), val(m + 1);
for (int i = 1; i <= m; ++i) {
cin >> time[i] >> val[i];
}
vector<vector<int>> dp(m + 1, vector<int>(t + 1, 0));
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= t; ++j) {
if (time[i] > j) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - time[i]] + val[i]);
}
}
}
cout << dp[m][t] << endl;
return 0;
}
A more complex variant appears in the weight measurement problem: given n weights, determine how many distinct positive masses can be measured by placing weights on either side of a balance. This extends the knapsack idea by allowing both addition and subtraction of weights. The state possible[i][w] indicates whether mass w can be formed using the first i weights. Transitions consider three cases: not using the current weight, adding it to the same side (increasing mass), or placing it on the opposite side (effectively subtracting its value, handled via asbolute difference).
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> w(n + 1);
int total = 0;
for (int i = 1; i <= n; ++i) {
cin >> w[i];
total += w[i];
}
vector<vector<bool>> possible(n + 1, vector<bool>(total + 1, false));
possible[0][0] = true;
for (int i = 1; i <= n; ++i) {
for (int mass = 0; mass <= total; ++mass) {
// Case 1: skip current weight
if (possible[i - 1][mass]) {
possible[i][mass] = true;
}
// Case 2: add to same side
if (mass >= w[i] && possible[i - 1][mass - w[i]]) {
possible[i][mass] = true;
}
// Case 3: place on opposite side (subtract)
int diff = abs(mass - w[i]);
if (possible[i - 1][diff]) {
possible[i][mass] = true;
}
}
}
int count = 0;
for (int i = 1; i <= total; ++i) {
if (possible[n][i]) ++count;
}
cout << count << endl;
return 0;
}