diff --git a/README.md b/README.md index c82d0ec..eae71e0 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ ## 1. Информация о студенте -**Номер группы**: 00-000 +**Номер группы**: 11-104 -**Фамилия и Имя**: Иванов Иван +**Фамилия и Имя**: Камалов Нияз ## 2. Описание задания diff --git a/src/bits.cpp b/src/bits.cpp index 37cf7a0..2045899 100644 --- a/src/bits.cpp +++ b/src/bits.cpp @@ -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 mask2indices(const std::vector& elems, int mask) { diff --git a/src/knapsack/backtracking.cpp b/src/knapsack/backtracking.cpp index d051dc2..684e5ad 100644 --- a/src/knapsack/backtracking.cpp +++ b/src/knapsack/backtracking.cpp @@ -35,13 +35,19 @@ namespace assignment { // ... если текущая "польза" максимальна, обновляем наилучшую "пользу" if (profit > best_profit) { - // ... + best_profit = profit; + best_profit_mask = mask; } // рассматриваем следующий элемент index += 1; + if (index == static_cast(profits.size())) { + return; + } // ... рекурсивные вызовы со включением/исключением следующего элемента + solve(profits, weights, capacity, index, mask, weight, profit, best_profit, best_profit_mask); + solve(profits, weights, capacity, index, set_bit(mask, index), weight + weights[index], profit + profits[index], best_profit, best_profit_mask); } -} // namespace assignment +} // namespace assignment \ No newline at end of file diff --git a/src/knapsack/bit_masking.cpp b/src/knapsack/bit_masking.cpp index 4160fef..051a891 100644 --- a/src/knapsack/bit_masking.cpp +++ b/src/knapsack/bit_masking.cpp @@ -33,6 +33,9 @@ namespace assignment { // вычисление общего веса рассматриваемых элементов const int curr_weight = sum_helper(masked_weights); + if (curr_weight > capacity) { + continue; + } // ... обработка случая превышения емкости рюкзака // массив из "пользы" рассматриваемых элементов @@ -41,12 +44,15 @@ namespace assignment { // вычисление общей "пользы" рассматриваемых элементов 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 \ No newline at end of file diff --git a/src/subset_sum/backtracking.cpp b/src/subset_sum/backtracking.cpp index c5c7469..6a44875 100644 --- a/src/subset_sum/backtracking.cpp +++ b/src/subset_sum/backtracking.cpp @@ -32,23 +32,35 @@ namespace assignment { } // Ограничение 1: текущая сумма должна быть меньше целевой - if (true /* ... */) { + if (sum > target_sum) { // если превысили целевую сумму, то сделать ее меньше уже не получится (все элементы множества положительные) return; } // Ограничение 2: "остаточная сумма" + "текущая сумма" должны быть больше или равны "целевой сумме" - if (true /* ... */) { + if (sum + residual < target_sum) { // сумму невозможно будет набрать с оставшимися элементами множества return; } // если найдено подмножество с целевой суммой, то сохраняем в результат это подмножество if (sum == target_sum) { + const auto num_elems = static_cast(set.size()); // N + auto subset = std::vector(); + for (int j = 0; j < num_elems; j++) { + if (is_bit_set(mask,j)) { + subset.push_back(j); + } + } + indices.push_back(subset); // ... сохранение в результат // ... нужно ли в этой ветке рекурсии рассматривать следующие элементы? } + if (index == static_cast(set.size() - 1)) { + return; + } + // рассматриваем следующий элемент index += 1; @@ -56,6 +68,8 @@ namespace assignment { residual -= set[index]; // рекурсивный вызов со включением/исключением элемента с текущим индексом ... + search(set, index, mask, sum, residual, target_sum, indices); + search(set, index, set_bit(mask, index), sum + set[index], residual, target_sum, indices); } } // namespace assignment \ No newline at end of file diff --git a/src/subset_sum/bit_masking.cpp b/src/subset_sum/bit_masking.cpp index 4deec18..ef5def4 100644 --- a/src/subset_sum/bit_masking.cpp +++ b/src/subset_sum/bit_masking.cpp @@ -7,19 +7,35 @@ namespace assignment { std::vector> SubsetSumBitMasking::search(const std::vector& set, int target_sum) const { - assert(target_sum > 0 && set.size() <= 16); - - std::vector> indices; + assert(set.size() <= 16); const auto num_elems = static_cast(set.size()); // N const int num_subsets = 1 << num_elems; // 2^N + // выделяем память + auto indices = std::vector>(); + // 1. Внешний цикл: пробегаемся по всем битовым маскам от 0..00 до 1..11 // 2. Внутренний цикл: проверка разрядов битовой маски и генерация подмножества, ассоциирующегося с этой маской // 3. Подсчет суммы текущего подмножества, сохранение индексов подмножества с целевой суммой в результат // Tips: можно пропустить итерацию, если сумма текущего подмножества стала больше целевой суммы + for (int i = 0; i < num_subsets; i++) { + auto subset = std::vector(); + int sum = 0; + for (int j = 0; j < num_elems; j++) { + if (is_bit_set(i,j)) { + subset.push_back(j); + sum += set[j]; + } + } + if (sum == target_sum) { + indices.push_back(subset); + } + } return indices; + + } } // namespace assignment \ No newline at end of file diff --git a/src/subsets/backtracking.cpp b/src/subsets/backtracking.cpp index 256dd5b..ab0dd81 100644 --- a/src/subsets/backtracking.cpp +++ b/src/subsets/backtracking.cpp @@ -26,15 +26,22 @@ namespace assignment { assert(mask >= 0 && index >= -1); // Ограничение: рассмотрены все элементы множества + const auto num_elems = static_cast(set.size()); // N if (index == static_cast(set.size()) - 1) { - - // ... сохранение полученного подмножества - + auto subset = std::vector(); + for (int j = 0; j < num_elems; j++) { + if (is_bit_set(mask,j)) { + subset.push_back(j); + } + } + subsets.push_back(subset); return; // возвращаемся по дереву рекурсии } index += 1; // рассматриваем следующий элемент + generate(set, index, mask, subsets); + generate(set, index, set_bit(mask, index), subsets); // здесь должны быть рекурсивные вызовы ... // включаем или не включаем элемент с текущим индексом в подмножество (используя битовую маску) } diff --git a/src/subsets/bit_masking.cpp b/src/subsets/bit_masking.cpp index feadd7e..c287ba6 100644 --- a/src/subsets/bit_masking.cpp +++ b/src/subsets/bit_masking.cpp @@ -13,11 +13,20 @@ namespace assignment { const int num_subsets = 1 << num_elems; // 2^N // выделяем память - auto subsets = std::vector>(num_subsets); + auto subsets = std::vector>(); // 1. Внешний цикл: пробегаемся по всем битовым маскам от 0..00 до 1..11 // 2. Внутренний цикл: проверка разрядов битовой маски и генерация подмножества, ассоциирующегося с этой маской // Tips: для проверки разряда бита на 1 (единицу) используйте функцию is_bit_set + for (int i = 0; i < num_subsets; i++) { + auto subset = std::vector(); + for (int j = 0; j < num_elems; j++) { + if (is_bit_set(i,j)) { + subset.push_back(j); + } + } + subsets.push_back(subset); + } return subsets; }