-
Notifications
You must be signed in to change notification settings - Fork 0
Added queens problem solutions #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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}") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Вместо |
||
| if is_valid(cords, n): | ||
| count += 1 | ||
| return count | ||
|
|
||
| n = int(input("Введите n: ")) # Можно до 6-ти, 7 уже не тянет (ждала больше минуты) | ||
| result = queens_counter(n) | ||
| print(f"Количество расстановок {n} ферзей: {result}") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) | ||
|
Comment on lines
+25
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нужно было добавить тут проверку |
||
| 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}") | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Можно писать формулки как в latex, если обернуть их в $$
$O(C^{n^2}_n \cdot n^2)$