Выбор предметов с максимальной стоимостью при ограничении по весу
W = int(input()) # вместимость рюкзака
n = int(input()) # количество предметов
w = [0] * (n + 1)
c = [0] * (n + 1)
for i in range(1, n + 1):
w[i] = int(input())
for i in range(1, n + 1):
c[i] = int(input())
dp = [[0] * (W + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, W + 1):
if j < w[i]:
dp[i][j] = dp[i - 1][j]
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + c[i])
print(dp[n][W])
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, W;
cin >> n >> W;
vector<int> w(n + 1);
for (int i = 1; i <= n; i++) {
cin >> w[i];
}
vector<int> c(n + 1);
for (int i = 1; i <= n; i++) {
cin >> c[i];
}
vector<vector<int>> dp(n + 1, vector<int>(W + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= W; j++) {
if (j < w[i]) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + c[i]);
}
}
}
cout << dp[n][W];
return 0;
}
W = int(input()) # вместимость рюкзака
n = int(input()) # количество предметов
A = [int(input()) for _ in range(n)] # веса предметов
dp = [[0] * (W + 1) for _ in range(n + 1)]
dp[0][0] = 1
for i in range(1, n + 1):
for j in range(W + 1):
if A[i - 1] <= j:
dp[i][j] = dp[i - 1][j] or dp[i - 1][j - A[i - 1]]
else:
dp[i][j] = dp[i - 1][j]
if dp[n][W] == 0:
print(0)
exit()
Z = []
i, j = n, W
while i != 0 or j != 0:
if dp[i - 1][j] == 1 and (j >= A[i - 1] and dp[i - 1][j - A[i - 1]] == 1):
print(-1)
exit()
else:
if dp[i - 1][j] == 1:
i -= 1
else:
i -= 1
j -= A[i]
Z.append(i + 1)
if len(Z) == 0:
print(0)
else:
print(*list(reversed(Z)))
#include <bits/stdc++.h>
using namespace std;
int main() {
int W, n;
cin >> W >> n;
vector<int> A(n);
for (int i = 0; i < n; i++) {
cin >> A[i];
}
vector<vector<bool>> dp(n + 1, vector<bool>(W + 1, false));
dp[0][0] = true;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= W; j++) {
if (A[i - 1] <= j) {
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - A[i - 1]];
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
if (!dp[n][W]) {
cout << 0;
return 0;
}
vector<int> Z;
int i = n, j = W;
while (i != 0 || j != 0) {
if (dp[i - 1][j] && (j >= A[i - 1] && dp[i - 1][j - A[i - 1]])) {
cout << -1;
return 0;
} else {
if (dp[i - 1][j]) {
i--;
} else {
i--;
j -= A[i];
Z.push_back(i + 1);
}
}
}
reverse(Z.begin(), Z.end());
for (int x : Z) {
cout << x << " ";
}
return 0;
}
Задача о рюкзаке (Knapsack problem) — это классическая задача ДП, в которой нужно выбрать предметы с максимальной суммарной стоимостью, не превышая заданную вместимость рюкзака.
Название "0/1" означает, что каждый предмет можно либо взять (1), либо не брать (0) — дробные части не допускаются.
Пусть dp[i][j] — максимальная стоимость, которую можно получить, используя первые i предметов и вместимость j.
Рекуррентная формула:
j < w[i] (текущий предмет не влезает), то dp[i][j] = dp[i-1][j]dp[i][j] = max(dp[i-1][j], dp[i-1][j - w[i]] + c[i])где w[i] — вес i-го предмета, c[i] — его стоимость.
Базовый случай: dp[0][j] = 0 (без предметов стоимость 0).
Временная сложность: O(n × W) — два вложенных цикла.
Пространственная сложность: O(n × W) — матрица dp.
Для нахождения набора предметов, дающих максимальную стоимость, используется обратный проход по таблице dp:
i = n, j = Wdp[i-1][j] == dp[i][j], то предмет i не взят → переходим к i-1i-1, j - w[i]Рассмотрим рюкзак вместимостью W = 10 и 4 предмета:
Предмет 1: вес = 6, стоимость = 30
Предмет 2: вес = 3, стоимость = 14
Предмет 3: вес = 4, стоимость = 16
Предмет 4: вес = 2, стоимость = 9
0 1 2 3 4 5 6 7 8 9 10
0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 30 30 30 30 30
2 0 0 0 14 14 14 30 30 30 44 44
3 0 0 0 14 16 16 30 30 30 44 46
4 0 0 9 14 16 25 30 30 39 44 46
Ответ: dp[4][10] = 46
Максимальная стоимость: 46
Набор предметов: 2 + 3 + 4 = 14 + 16 + 9 = 39? нет, 2+4 = 14+9=23...
Оптимальный набор: предметы 1 и 4 (вес 6+2=8, стоимость 30+9=39) или предметы 2,3,4 (вес 3+4+2=9, стоимость 14+16+9=39) — но в таблице 46?
Проверим: предметы 1 и 3? вес 6+4=10, стоимость 30+16=46! Да, это оптимально.
Оптимальный набор: предметы 1 и 3 (вес 10, стоимость 46)
Введите параметры задачи и найдите максимальную стоимость: