diff --git a/src/complexity_4/bit_operations.py b/src/complexity_4/bit_operations.py new file mode 100644 index 0000000..468c33d --- /dev/null +++ b/src/complexity_4/bit_operations.py @@ -0,0 +1,20 @@ +def n_queens_fast(n): + """Оптимизированное решение с использованием битовых операций""" + + def solve(row, cols, diag1, diag2): + nonlocal count + if row == n: + count += 1 + return + + available = ((1 << n) - 1) & ~(cols | diag1 | diag2) + + while available: + pos = available & -available + available -= pos + + solve(row + 1, cols | pos, (diag1 | pos) << 1, (diag2 | pos) >> 1) + + count = 0 + solve(0, 0, 0, 0) + return count diff --git a/src/complexity_4/complexity.md b/src/complexity_4/complexity.md new file mode 100644 index 0000000..46f1227 --- /dev/null +++ b/src/complexity_4/complexity.md @@ -0,0 +1,29 @@ +Оценка сложности решений +1. Переборное решение +Сложность: O(N! × N²) + +Обоснование: +Генерируются все перестановки N элементов: N! вариантов. +Для каждой перестановки проверяется корректность за O(N²) в худшем случае. +Фактическое время работы растет факториально, что делает решение непригодным для N > 10. + +2. Рекурсивное решение (backtracking) +Сложность: O(N!) в худшем случае, но на практике меньше + +Обоснование: +Алгоритм использует возврат (backtracking), отсекая заведомо неверные расстановки. +В худшем случае перебирается N! вариантов. +Благодаря отсечениям (проверка столбцов и диагоналей за O(1)) работает значительно быстрее переборного решения. + +3. Оптимизированное решение (битовые операции) +Сложность: O(N!), но с существенно меньшей константой + +Обоснование: +Использует битовые операции для максимально быстрой проверки доступных позиций. +Все операции (проверка и установка позиций) выполняются за O(1). +Константа времени выполнения в 10-100 раз меньше, чем у обычного backtracking. + +Итоги: +Все решения имеют факториальную сложность в худшем случае +Для N > 16 требуется принципиально иной подход или эвристические алгоритмы +Оптимизированное решение наиболее эффективно благодаря минимальным накладным расходам \ No newline at end of file diff --git a/src/complexity_4/enumeration.py b/src/complexity_4/enumeration.py new file mode 100644 index 0000000..18947f3 --- /dev/null +++ b/src/complexity_4/enumeration.py @@ -0,0 +1,27 @@ +import itertools + + +def is_valid(board): + """Проверяет, является ли расстановка корректной""" + n = len(board) + for i in range(n): + for j in range(i + 1, n): + if board[i] == board[j]: + return False + + if abs(board[i] - board[j]) == abs(i - j): + return False + return True + + +def n_queens_bruteforce(n): + """Перебор всех возможных расстановок""" + if n < 1 or n > 10: + return 0 + + count = 0 + + for permutation in itertools.permutations(range(n)): + if is_valid(permutation): + count += 1 + return count diff --git a/src/complexity_4/recursion.py b/src/complexity_4/recursion.py new file mode 100644 index 0000000..09f7917 --- /dev/null +++ b/src/complexity_4/recursion.py @@ -0,0 +1,26 @@ +def n_queens_recursive(n): + """Рекурсивное решение с возвратом""" + + def backtrack(row, cols, diag1, diag2): + nonlocal count + if row == n: + count += 1 + return + + for col in range(n): + if cols[col] or diag1[row + col] or diag2[row - col + n - 1]: + continue + + cols[col] = diag1[row + col] = diag2[row - col + n - 1] = True + backtrack(row + 1, cols, diag1, diag2) + + cols[col] = diag1[row + col] = diag2[row - col + n - 1] = False + + count = 0 + + cols = [False] * n + diag1 = [False] * (2 * n - 1) + diag2 = [False] * (2 * n - 1) + + backtrack(0, cols, diag1, diag2) + return count