Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

## 1. Информация о студенте

**Номер группы**: 00-000
**Номер группы**: 11-109

**Фамилия и Имя**: Иванов Иван
**Фамилия и Имя**: Лямкин Сергей

## 2. Описание задания

Expand Down
4 changes: 2 additions & 2 deletions src/bits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ namespace assignment {

bool is_bit_set(int mask, int pos) {
assert(mask >= 0 && pos >= 0 && pos < 30);
return false;
return (mask & 1 << pos) != 0;
}

int set_bit(int mask, int pos) {
assert(mask >= 0 && pos >= 0 && pos < 30);
return 0;
return mask | 1 << pos;
}

std::vector<int> mask2indices(const std::vector<int>& elems, int mask) {
Expand Down
17 changes: 16 additions & 1 deletion src/knapsack/backtracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,28 @@ namespace assignment {

// ... если текущая "польза" максимальна, обновляем наилучшую "пользу"
if (profit > best_profit) {
// ...
best_profit = profit;
best_profit_mask = mask;
}

// рассматриваем следующий элемент
index += 1;

// ... рекурсивные вызовы со включением/исключением следующего элемента
const auto mask_profits = mask2elems(profits, mask);
int now_profit = 0;
for (int one_profit : mask_profits) {
now_profit += one_profit;
}
const auto masked_weights = mask2elems(weights, mask);
int now_weight = 0;
for (int one_weight : masked_weights) {
now_weight += one_weight;
}
solve(profits, weights, capacity, index, mask, now_weight, now_profit, best_profit, best_profit_mask);
solve(profits, weights, capacity, index,
set_bit(mask, index), now_weight + weights[index],
now_profit + profits[index], best_profit, best_profit_mask);
}

} // namespace assignment
13 changes: 11 additions & 2 deletions src/knapsack/bit_masking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ namespace assignment {
int best_profit_mask = 0;

// Tip: What if the weight is equal to the max weight? Can we stop the process?

if (capacity == sum_helper(weights)) {
return mask2indices(profits, num_subsets - 1);
}
// 0..00, 0..01, 0..10, 0..11, ..., 1..11
for (int mask = 0; mask < num_subsets; mask++) { // 2^N

Expand All @@ -34,19 +36,26 @@ namespace assignment {
const int curr_weight = sum_helper(masked_weights);

// ... обработка случая превышения емкости рюкзака
if (curr_weight > capacity) {
continue;
}

// массив из "пользы" рассматриваемых элементов
const auto masked_profits = mask2elems(profits, mask);

// вычисление общей "пользы" рассматриваемых элементов
const int curr_profit = sum_helper(masked_profits);

if (curr_profit > best_profit) {
best_profit = curr_profit;
best_profit_mask = mask;
}
// ... обработка случая нахождения большего значения "пользы"
}

// ... возвращение итогового результата: используйте mask2indices;

return {};
return mask2indices(profits, best_profit_mask);
}

} // namespace assignment
15 changes: 12 additions & 3 deletions src/subset_sum/backtracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,39 @@ namespace assignment {
}

// Ограничение 1: текущая сумма должна быть меньше целевой
if (true /* ... */) {
if (sum > target_sum) {
// если превысили целевую сумму, то сделать ее меньше уже не получится (все элементы множества положительные)
return;
}

// Ограничение 2: "остаточная сумма" + "текущая сумма" должны быть больше или равны "целевой сумме"
if (true /* ... */) {
if (residual + sum < target_sum) {
// сумму невозможно будет набрать с оставшимися элементами множества
return;
}

// если найдено подмножество с целевой суммой, то сохраняем в результат это подмножество
if (sum == target_sum) {
// ... сохранение в результат
indices.push_back(mask2indices(set, mask));
// ... нужно ли в этой ветке рекурсии рассматривать следующие элементы?
}

// рассматриваем следующий элемент
index += 1;

// обновляется несмотря на включение/исключение элемента => почему?
// обновляется несмотря на включение/исключение элемента => почему? (потому что мы не сможем
// добавить в множество элемент, который уже рассмотрели на прошлых шагах)
residual -= set[index];

// рекурсивный вызов со включением/исключением элемента с текущим индексом ...
std::vector<int> subset = mask2elems(set, mask);
search(set, index, mask,
std::accumulate(subset.begin(), subset.end(), 0),
residual, target_sum, indices);
search(set, index, set_bit(mask, index),
std::accumulate(subset.begin(),subset.end(), 0) + set[index],
residual, target_sum, indices);
}

} // namespace assignment
15 changes: 15 additions & 0 deletions src/subset_sum/bit_masking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ namespace assignment {
const auto num_elems = static_cast<int>(set.size()); // N
const int num_subsets = 1 << num_elems; // 2^N

for (int mask = 0; mask < num_subsets; mask++) {
for (int pos = 0; pos < num_elems; pos++) {
std::vector<int> subset = mask2indices(set, mask);
int summa = 0;
for (int index : subset) {
summa += set[index];
}
if (summa > target_sum) {
break;
}
if (summa == target_sum) {
indices.push_back(subset);
}
}
}
// 1. Внешний цикл: пробегаемся по всем битовым маскам от 0..00 до 1..11
// 2. Внутренний цикл: проверка разрядов битовой маски и генерация подмножества, ассоциирующегося с этой маской
// 3. Подсчет суммы текущего подмножества, сохранение индексов подмножества с целевой суммой в результат
Expand Down
4 changes: 3 additions & 1 deletion src/subsets/backtracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ namespace assignment {

// Ограничение: рассмотрены все элементы множества
if (index == static_cast<int>(set.size()) - 1) {

subsets.push_back(mask2indices(set, mask));
// ... сохранение полученного подмножества

return; // возвращаемся по дереву рекурсии
}

index += 1; // рассматриваем следующий элемент

generate(set, index, mask, subsets);
generate(set, index, set_bit(mask, index), subsets);
// здесь должны быть рекурсивные вызовы ...
// включаем или не включаем элемент с текущим индексом в подмножество (используя битовую маску)
}
Expand Down
7 changes: 7 additions & 0 deletions src/subsets/bit_masking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ namespace assignment {
// выделяем память
auto subsets = std::vector<std::vector<int>>(num_subsets);

for (int mask = 0; mask < num_subsets; mask++) {
for (int pos = 0; pos < num_elems; pos++) {
if (is_bit_set(mask, pos)) {
subsets[mask].push_back(pos);
}
}
}
// 1. Внешний цикл: пробегаемся по всем битовым маскам от 0..00 до 1..11
// 2. Внутренний цикл: проверка разрядов битовой маски и генерация подмножества, ассоциирующегося с этой маской
// Tips: для проверки разряда бита на 1 (единицу) используйте функцию is_bit_set
Expand Down