From 0b65320a23f44af4c3bf7d80ac86a47f2447860a Mon Sep 17 00:00:00 2001 From: DolzhenkoAlexa Date: Fri, 28 Nov 2025 13:50:01 +0300 Subject: [PATCH] Added queens problem solutions --- src/hw_queens/complexity.md | 24 ++++++++++++++++++++ src/hw_queens/fastest_queens.py | 31 ++++++++++++++++++++++++++ src/hw_queens/itertools_queens.py | 33 +++++++++++++++++++++++++++ src/hw_queens/recursive_queens.py | 37 +++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 src/hw_queens/complexity.md create mode 100644 src/hw_queens/fastest_queens.py create mode 100644 src/hw_queens/itertools_queens.py create mode 100644 src/hw_queens/recursive_queens.py diff --git a/src/hw_queens/complexity.md b/src/hw_queens/complexity.md new file mode 100644 index 0000000..2ee08d2 --- /dev/null +++ b/src/hw_queens/complexity.md @@ -0,0 +1,24 @@ +# Оценка сложности решений задачи о расстановке ферзей + +## 1. Переборное решение +- Очень медленное решение +- all_cells содержит n^2 элементов (все клетки доски), и при помощи combinations получаем C(n^2, n) +- is_valid в худшем случае даст n^2 операций +Итог: О(С(n^2,n) * n^2) +Позволяет получить получить решения для n<=6 + + + +## 2. Рекурсивное решение +- Рекурсия - n! +- Проверка на валидность - n^2 +Итог: O(n! * n^2) +Позволяет получить получить решения для n<=8 + + + +## 3. Самое быстрое решение +- Рекурсия - n! +- Проверка наличия элементов во всех множествах, добавление/удаление из sets: O(1) +Итог: O(n!) +Позволяет получить получить решения для n<=13-14 \ No newline at end of file diff --git a/src/hw_queens/fastest_queens.py b/src/hw_queens/fastest_queens.py new file mode 100644 index 0000000..1286a03 --- /dev/null +++ b/src/hw_queens/fastest_queens.py @@ -0,0 +1,31 @@ +def queens_counter(n): + columns = set() + diag1 = set() + diag2 = set() + + def backtrack(row): + if row == n: + return 1 # нашли +1 решение + + count = 0 + for col in range(n): + if col in columns or (row + col) in diag1 or (row - col) in diag2: + continue + + columns.add(col) + diag1.add(row + col) # диагонали слева направо (/) + diag2.add(row - col) # диагонали справа налево (\) + + count += backtrack(row + 1) # суммируем решения из этой ветки + + columns.remove(col) + diag1.remove(row + col) + diag2.remove(row - col) + + return count + + return backtrack(0) # Рекурсия + +n = int(input("Введите n: ")) # Можно до 13-ти включительно, 14 выдает меньше чем за полминуты +result = queens_counter(n) +print(f"Количество расстановок {n} ферзей: {result}") diff --git a/src/hw_queens/itertools_queens.py b/src/hw_queens/itertools_queens.py new file mode 100644 index 0000000..e2a50a7 --- /dev/null +++ b/src/hw_queens/itertools_queens.py @@ -0,0 +1,33 @@ +import itertools + +# Функция для проверки того, что ферзи не бьют друг друга, то есть расстановка валидная +def is_valid(cords, n): + # Проверяем строки + for i in range(n): + for j in range(i + 1, n): + # Если два ферзя в одной строке + if cords[i][0] == cords[j][0]: + return False + # Если два ферзя в одном столбце + if cords[i][1] == cords[j][1]: + return False + # Если два ферзя на одной диагонали + if abs(cords[i][0] - cords[j][0]) == abs(cords[i][1] - cords[j][1]): + return False + return True + +def queens_counter(n): + count = 0 # Счетчик правильных расстановок ферзей + + # Генерируем все возможные наборы из N различных клеток + all_cells = [(i, j) for i in range(n) for j in range(n)] + + # Возьмем все расстановки без повторяющихся клеток + for cords in itertools.combinations(all_cells, n): + if is_valid(cords, n): + count += 1 + return count + +n = int(input("Введите n: ")) # Можно до 6-ти, 7 уже не тянет (ждала больше минуты) +result = queens_counter(n) +print(f"Количество расстановок {n} ферзей: {result}") \ No newline at end of file diff --git a/src/hw_queens/recursive_queens.py b/src/hw_queens/recursive_queens.py new file mode 100644 index 0000000..a5196b1 --- /dev/null +++ b/src/hw_queens/recursive_queens.py @@ -0,0 +1,37 @@ +# Функция для проверки того, что ферзи не бьют друг друга, то есть расстановка валидная +def is_valid(cords, n): + # Проверяем строки и столбцы + rows = [q[0] for q in cords] + columns = [q[1] for q in cords] + if len(set(rows)) != n or len(set(columns)) != n: + return False + + # Проверяем диагонали + for i in range(n): + for j in range(i + 1, n): + if abs(cords[i][0] - cords[j][0]) == abs(cords[i][1] - cords[j][1]): + return False + return True + + +def queens_counter(row, n, placed_queens): + count = 0 + if row == n: # Если дошли до конца доски, то завершаем + if is_valid(placed_queens, n): + return 1 + return 0 + + for column in range(n): + if (row, column) not in placed_queens: # Проверка, чтобы не было двух (0,1) + new = placed_queens + [(row, column)] + count += queens_counter(row + 1, n, new) + return count + + +def count_queens_recursive(n): + return queens_counter(0, n, []) + + +n = int(input("Введите n: ")) #Можно до 7-ми быстро, 8 выдает у меня за секунд 15 +result = count_queens_recursive(n) +print(f"Количество расстановок {n} ферзей: {result}") \ No newline at end of file