diff --git a/README.md b/README.md index c82d0ec..fd5dd40 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ ## 1. Информация о студенте -**Номер группы**: 00-000 +**Номер группы**: 11-109 -**Фамилия и Имя**: Иванов Иван +**Фамилия и Имя**: Краденова Дарья ## 2. Описание задания diff --git a/src/bits.cpp b/src/bits.cpp index 37cf7a0..030f5b1 100644 --- a/src/bits.cpp +++ b/src/bits.cpp @@ -1,17 +1,18 @@ #include "assignment/bits.hpp" -#include // assert +#include namespace assignment { bool is_bit_set(int mask, int pos) { assert(mask >= 0 && pos >= 0 && pos < 30); - return false; + return (mask &(1 << pos)); } + 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) { @@ -34,14 +35,14 @@ namespace assignment { std::vector masked_elems; - for (int pos = 0; pos < static_cast(elems.size()); pos++) { + for (int idx = 0; idx < static_cast(elems.size()); idx++) { - if (is_bit_set(mask, pos)) { - masked_elems.push_back(elems[pos]); + if (is_bit_set(mask, idx)) { + masked_elems.push_back(elems[idx]); } } return masked_elems; } -} // namespace assignment \ No newline at end of file +} \ No newline at end of file diff --git a/src/knapsack/backtracking.cpp b/src/knapsack/backtracking.cpp index d051dc2..fb0059b 100644 --- a/src/knapsack/backtracking.cpp +++ b/src/knapsack/backtracking.cpp @@ -9,12 +9,9 @@ namespace assignment { std::vector KnapsackBacktracking::solve(const Profits& profits, const Weights& weights, int capacity) const { assert(profits.size() == weights.size() && capacity > 0); - // результат: наибольшая "польза" int best_profit = 0; int best_profit_mask = 0; - // вызов вспомогательного метода: обратите внимание на входные аргументы - // и на то, как они передаются (по значению или ссылке, почему так?) solve(profits, weights, capacity, -1, 0, 0, 0, best_profit, best_profit_mask); return mask2indices(profits, best_profit_mask); @@ -23,25 +20,22 @@ namespace assignment { 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; - } + if (index == static_cast(profits.size())) {return;} - // Ограничение 1: превышение лимита емкости рюкзака - if (weight > capacity) { - return; - } + if (weight > capacity) {return;} - // ... если текущая "польза" максимальна, обновляем наилучшую "пользу" if (profit > best_profit) { - // ... + best_profit = profit; + best_profit_mask = mask; + + + } - // рассматриваем следующий элемент 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..d4d4208 100644 --- a/src/knapsack/bit_masking.cpp +++ b/src/knapsack/bit_masking.cpp @@ -3,11 +3,10 @@ #include // assert #include // accumulate -#include "assignment/bits.hpp" // mask2elems, mask2indices +#include "assignment/bits.hpp" namespace assignment { - // вспомогательная функция подсчета суммы элементов массива static int sum_helper(const std::vector& arr) { return std::accumulate(arr.begin(), arr.end(), 0); } @@ -15,25 +14,25 @@ namespace assignment { std::vector KnapsackBitMasking::solve(const Profits& profits, const Weights& weights, int capacity) const { assert(profits.size() == weights.size() && capacity > 0); - const auto num_elems = static_cast(profits.size()); // N - const int num_subsets = 1 << num_elems; // 2^N + const auto num_elems = static_cast(profits.size()); + const int num_subsets = 1 << num_elems; - // результат: лучшая найденная "польза" (+ маска для получения элементов) int best_profit = 0; int best_profit_mask = 0; - // Tip: What if the weight is equal to the max weight? Can we stop the process? - - // 0..00, 0..01, 0..10, 0..11, ..., 1..11 + if(capacity == sum_helper(weights)){ + return mask2indices(profits,num_subsets - 1); + } for (int mask = 0; mask < num_subsets; mask++) { // 2^N - // массив из весов рассматриваемых элементов const auto masked_weights = mask2elems(weights, mask); - // вычисление общего веса рассматриваемых элементов const int curr_weight = sum_helper(masked_weights); // ... обработка случая превышения емкости рюкзака + if(curr_weight > capacity) { + continue; + } // массив из "пользы" рассматриваемых элементов const auto masked_profits = mask2elems(profits, mask); @@ -41,12 +40,16 @@ 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..99fb80b 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 ((residual + sum) < 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..e40d6eb 100644 --- a/src/subset_sum/bit_masking.cpp +++ b/src/subset_sum/bit_masking.cpp @@ -19,6 +19,19 @@ namespace assignment { // 3. Подсчет суммы текущего подмножества, сохранение индексов подмножества с целевой суммой в результат // Tips: можно пропустить итерацию, если сумма текущего подмножества стала больше целевой суммы + for(int mask = 0; mask < num_subsets; mask++) { + std::vector subset = mask2indices(set, mask); + int curr_sum = 0; + for (int idx = 0; idx < subset.size(); idx++) { + curr_sum += set[static_cast(subset[idx])]; + if (curr_sum > target_sum) { + break; + } + } + if (curr_sum == target_sum) { + indices.push_back(subset); + } + } return indices; } diff --git a/src/subsets/backtracking.cpp b/src/subsets/backtracking.cpp index 256dd5b..af3830a 100644 --- a/src/subsets/backtracking.cpp +++ b/src/subsets/backtracking.cpp @@ -2,20 +2,19 @@ #include // assert -#include "assignment/bits.hpp" // is_bit_set, set_bit, mask2indices +#include "assignment/bits.hpp" namespace assignment { std::vector> SubsetsBacktracking::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 + const auto num_elems = static_cast(set.size()); + const int num_subsets = 1 << num_elems; auto subsets = std::vector>(); subsets.reserve(num_subsets); - // вызов вспомогательной функции: обратите внимание на начальное значение индекса и маски generate(set, -1, 0, subsets); return subsets; @@ -25,18 +24,19 @@ namespace assignment { std::vector>& subsets) const { assert(mask >= 0 && index >= -1); - // Ограничение: рассмотрены все элементы множества if (index == static_cast(set.size()) - 1) { - // ... сохранение полученного подмножества + subsets.push_back(mask2indices(set,mask)); - return; // возвращаемся по дереву рекурсии + return; } - index += 1; // рассматриваем следующий элемент + index += 1; - // здесь должны быть рекурсивные вызовы ... - // включаем или не включаем элемент с текущим индексом в подмножество (используя битовую маску) + + generate(set,index,mask,subsets); + + generate(set,index, set_bit(mask,index),subsets); } } // namespace assignment \ No newline at end of file diff --git a/src/subsets/bit_masking.cpp b/src/subsets/bit_masking.cpp index feadd7e..08b3bf4 100644 --- a/src/subsets/bit_masking.cpp +++ b/src/subsets/bit_masking.cpp @@ -1,8 +1,8 @@ #include "assignment/subsets/bit_masking.hpp" -#include // assert +#include -#include "assignment/bits.hpp" // is_bit_set +#include "assignment/bits.hpp" namespace assignment { @@ -12,14 +12,18 @@ namespace assignment { const auto num_elems = static_cast(set.size()); // N const int num_subsets = 1 << num_elems; // 2^N - // выделяем память auto subsets = std::vector>(num_subsets); - // 1. Внешний цикл: пробегаемся по всем битовым маскам от 0..00 до 1..11 - // 2. Внутренний цикл: проверка разрядов битовой маски и генерация подмножества, ассоциирующегося с этой маской - // Tips: для проверки разряда бита на 1 (единицу) используйте функцию is_bit_set + for(int mask = 0; mask < num_subsets; mask++) { + std::vector curr_subset; + for (int position = 0; position < num_elems; position++) { + if (is_bit_set(mask, position)) { + subsets[mask].push_back(position); + } + } + } return subsets; } -} // namespace assignment \ No newline at end of file +} \ No newline at end of file