From 2ef810d7f66ad7378374555f57c979d0fabb9f24 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Sat, 3 Sep 2022 11:39:12 +0000 Subject: [PATCH 1/3] Setting up GitHub Classroom Feedback From 21ff65085987ce44e596de6bf06e299d47704a42 Mon Sep 17 00:00:00 2001 From: lookisrr Date: Mon, 5 Sep 2022 10:35:16 +0300 Subject: [PATCH 2/3] 1 --- src/bits.cpp | 6 ++-- src/knapsack/backtracking.cpp | 7 +++-- src/knapsack/bit_masking.cpp | 9 +++++- src/subset_sum/backtracking.cpp | 8 ++++-- src/subset_sum/bit_masking.cpp | 49 +++++++++++++++++++++++++-------- src/subsets/backtracking.cpp | 39 ++++++++------------------ 6 files changed, 71 insertions(+), 47 deletions(-) diff --git a/src/bits.cpp b/src/bits.cpp index 37cf7a0..6712d98 100644 --- a/src/bits.cpp +++ b/src/bits.cpp @@ -5,13 +5,13 @@ namespace assignment { bool is_bit_set(int mask, int pos) { - assert(mask >= 0 && pos >= 0 && pos < 30); - return false; + assert(mask >= 0 && pos >= 0 && pos < 30); // pos < макс. кол-ва бит в маске + 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..df17124 100644 --- a/src/knapsack/backtracking.cpp +++ b/src/knapsack/backtracking.cpp @@ -35,13 +35,16 @@ namespace assignment { // ... если текущая "польза" максимальна, обновляем наилучшую "пользу" if (profit > best_profit) { - // ... + best_profit_mask = mask; + best_profit = profit; } // рассматриваем следующий элемент index += 1; + solve(profits,weights,capacity,index, set_bit(mask,index),weight + weights[index],profit + profits[index],best_profit,best_profit_mask); + solve(profits,weights,capacity,index,mask,weight,profit,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..a0ed7eb 100644 --- a/src/knapsack/bit_masking.cpp +++ b/src/knapsack/bit_masking.cpp @@ -34,6 +34,9 @@ namespace assignment { const int curr_weight = sum_helper(masked_weights); // ... обработка случая превышения емкости рюкзака + if (curr_weight > capacity){ + continue; + } // массив из "пользы" рассматриваемых элементов const auto masked_profits = mask2elems(profits, mask); @@ -42,11 +45,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..0c13bf7 100644 --- a/src/subset_sum/backtracking.cpp +++ b/src/subset_sum/backtracking.cpp @@ -32,13 +32,13 @@ namespace assignment { } // Ограничение 1: текущая сумма должна быть меньше целевой - if (true /* ... */) { + if (sum > target_sum) { // если превысили целевую сумму, то сделать ее меньше уже не получится (все элементы множества положительные) return; } // Ограничение 2: "остаточная сумма" + "текущая сумма" должны быть больше или равны "целевой сумме" - if (true /* ... */) { + if (sum + residual < target_sum) { // сумму невозможно будет набрать с оставшимися элементами множества return; } @@ -47,6 +47,8 @@ namespace assignment { if (sum == target_sum) { // ... сохранение в результат // ... нужно ли в этой ветке рекурсии рассматривать следующие элементы? + indices.push_back(mask2indices(set, mask)); + return; } // рассматриваем следующий элемент @@ -56,6 +58,8 @@ namespace assignment { residual -= set[index]; // рекурсивный вызов со включением/исключением элемента с текущим индексом ... + search(set, index, set_bit(mask, index), sum + set[index], residual, target_sum, indices); + search(set, index, mask, sum, 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..df17124 100644 --- a/src/subset_sum/bit_masking.cpp +++ b/src/subset_sum/bit_masking.cpp @@ -1,25 +1,50 @@ -#include "assignment/subset_sum/bit_masking.hpp" +#include "assignment/knapsack/backtracking.hpp" #include // assert -#include "assignment/bits.hpp" // is_bit_set, mask2indices +#include "assignment/bits.hpp" namespace assignment { - std::vector> SubsetSumBitMasking::search(const std::vector& set, int target_sum) const { - assert(target_sum > 0 && set.size() <= 16); + std::vector KnapsackBacktracking::solve(const Profits& profits, const Weights& weights, int capacity) const { + assert(profits.size() == weights.size() && capacity > 0); - std::vector> indices; + // результат: наибольшая "польза" + int best_profit = 0; + int best_profit_mask = 0; - const auto num_elems = static_cast(set.size()); // N - const int num_subsets = 1 << num_elems; // 2^N + // вызов вспомогательного метода: обратите внимание на входные аргументы + // и на то, как они передаются (по значению или ссылке, почему так?) + solve(profits, weights, capacity, -1, 0, 0, 0, best_profit, best_profit_mask); - // 1. Внешний цикл: пробегаемся по всем битовым маскам от 0..00 до 1..11 - // 2. Внутренний цикл: проверка разрядов битовой маски и генерация подмножества, ассоциирующегося с этой маской - // 3. Подсчет суммы текущего подмножества, сохранение индексов подмножества с целевой суммой в результат - // Tips: можно пропустить итерацию, если сумма текущего подмножества стала больше целевой суммы + return mask2indices(profits, best_profit_mask); + } + + void KnapsackBacktracking::solve(const Profits& profits, const Weights& weights, int capacity, int index, int mask, + int weight, int profit, int& best_profit, int& best_profit_mask) const { + + // Ограничение 0: выход за пределы + if (index == static_cast(profits.size())) { + return; + } + + // Ограничение 1: превышение лимита емкости рюкзака + if (weight > capacity) { + return; + } + + // ... если текущая "польза" максимальна, обновляем наилучшую "пользу" + if (profit > best_profit) { + best_profit_mask = mask; + best_profit = profit; + } + + // рассматриваем следующий элемент + index += 1; + solve(profits,weights,capacity,index, set_bit(mask,index),weight + weights[index],profit + profits[index],best_profit,best_profit_mask); + solve(profits,weights,capacity,index,mask,weight,profit,best_profit,best_profit_mask ); - return indices; + // ... рекурсивные вызовы со включением/исключением следующего элемента } } // namespace assignment \ No newline at end of file diff --git a/src/subsets/backtracking.cpp b/src/subsets/backtracking.cpp index 256dd5b..477232e 100644 --- a/src/subsets/backtracking.cpp +++ b/src/subsets/backtracking.cpp @@ -1,42 +1,27 @@ -#include "assignment/subsets/backtracking.hpp" +#include "assignment/subsets/bit_masking.hpp" #include // assert -#include "assignment/bits.hpp" // is_bit_set, set_bit, mask2indices +#include "assignment/bits.hpp" // is_bit_set namespace assignment { - std::vector> SubsetsBacktracking::generate(const std::vector& set) const { + std::vector> SubsetsBitMasking::generate(const std::vector& set) const { assert(set.size() <= 16); const auto num_elems = static_cast(set.size()); // N const int num_subsets = 1 << num_elems; // 2^N - - auto subsets = std::vector>(); - subsets.reserve(num_subsets); - - // вызов вспомогательной функции: обратите внимание на начальное значение индекса и маски - generate(set, -1, 0, subsets); - - return subsets; - } - - void SubsetsBacktracking::generate(const std::vector& set, int index, int mask, - std::vector>& subsets) const { - assert(mask >= 0 && index >= -1); - - // Ограничение: рассмотрены все элементы множества - if (index == static_cast(set.size()) - 1) { - - // ... сохранение полученного подмножества - - return; // возвращаемся по дереву рекурсии + auto subsets = std::vector>(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); + } + } } - index += 1; // рассматриваем следующий элемент - - // здесь должны быть рекурсивные вызовы ... - // включаем или не включаем элемент с текущим индексом в подмножество (используя битовую маску) + return subsets; } } // namespace assignment \ No newline at end of file From a021c1b56e137c3e75af735d3352bf47e70346d2 Mon Sep 17 00:00:00 2001 From: lookisrr Date: Mon, 5 Sep 2022 10:53:04 +0300 Subject: [PATCH 3/3] 1 --- main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/main.cpp b/main.cpp index d758716..e7d96e6 100644 --- a/main.cpp +++ b/main.cpp @@ -41,3 +41,4 @@ int main() { return 0; } +# \ No newline at end of file