-
Notifications
You must be signed in to change notification settings - Fork 0
Домашнее задание 4.1. Задача о расстановке ферзей. Разгуляева А.И. #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,78 @@ | ||
| # ruff.toml | ||
| target-version = "py311" | ||
| line-length = 100 | ||
|
|
||
| # включить все основные правила | ||
| select = [ | ||
| "E", # pycodestyle errors | ||
| "W", # pycodestyle warnings | ||
| "F", # Pyflakes | ||
| "I", # isort | ||
| "N", # pep8-naming | ||
| "UP", # pyupgrade | ||
| "YTT", # flake8-2020 | ||
| "S", # flake8-bandit | ||
| "A", # flake8-builtins | ||
| "COM", # flake8-commas | ||
| "C4", # flake8-comprehensions | ||
| "DTZ", # flake8-datetimez | ||
| "T10", # flake8-debugger | ||
| "EM", # flake8-errmsg | ||
| "EXE", # flake8-executable | ||
| "ISC", # flake8-implicit-str-concat | ||
| "ICN", # flake8-import-conventions | ||
| "G", # flake8-logging-format | ||
| "INP", # flake8-no-pep420 | ||
| "PIE", # flake8-pie | ||
| "T20", # flake8-print | ||
| "PYI", # flake8-pyi | ||
| "PT", # flake8-pytest-style | ||
| "Q", # flake8-quotes | ||
| "RSE", # flake8-raise | ||
| "RET", # flake8-return | ||
| "SLF", # flake8-self | ||
| "SIM", # flake8-simplify | ||
| "TID", # flake8-tidy-imports | ||
| "TCH", # flake8-type-checking | ||
| "INT", # flake8-gettext | ||
| "ARG", # flake8-unused-arguments | ||
| "FBT", # flake8-boolean-trap | ||
| "B", # flake8-bugbear | ||
| "AIR", # flake8-airflow | ||
| "PERF", # flake8-perflint | ||
| ] | ||
|
|
||
| # игнорировать правила | ||
| ignore = [ | ||
| "E501", # line too long - handled by formatter | ||
| "S101", # assert used - ok in tests | ||
| "T201", # print found - sometimes needed | ||
| "COM812", # trailing comma missing - not always required | ||
| ] | ||
|
|
||
| # настройки для конкретных файлов | ||
| [per-file-ignores] | ||
| "__init__.py" = ["F401"] # Unused imports allowed in __init__.py | ||
| "tests/**" = ["S101", "SLF001"] # Allow assert and self in tests | ||
| "**/migrations/**" = ["ALL"] # Ignore all in migrations | ||
|
|
||
| # настройки форматтера | ||
| [format] | ||
| indent-style = "space" | ||
| quote-style = "double" | ||
| skip-magic-trailing-comma = false | ||
| line-ending = "auto" | ||
|
|
||
| # настройки для конкретных правил | ||
| [flake8-quotes] | ||
| docstring-quotes = "double" | ||
| inline-quotes = "double" | ||
|
|
||
| [flake8-tidy-imports] | ||
| ban-relative-imports = "all" | ||
|
|
||
| [isort] | ||
| known-first-party = ["myapp"] | ||
| lines-after-imports = 2 | ||
| combine-as-imports = true | ||
| split-on-trailing-comma = true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Оценка сложности решений задачи о расстановке ферзей | ||
|
|
||
| ## 1. Переборное решение (bruteforce) | ||
|
|
||
| **Сложность:** O(N! * N²) | ||
|
|
||
| **Обоснование:** | ||
| - Генерируются все перестановки из N элементов: O(N!) | ||
| - Для каждой перестановки выполняется проверка валидности за O(N²) | ||
| - Проверка включает сравнение всех пар ферзей (N*(N-1)/2 сравнений) | ||
|
|
||
| **Применение:** Только для очень маленьких N (N ≤ 10) | ||
|
|
||
| ## 2. Рекурсивное решение (backtracking) | ||
|
|
||
| **Сложность:** O(N!) | ||
|
|
||
| **Обоснование:** | ||
| - В худшем случае перебираются все возможные расстановки | ||
| - Отсечение невалидных ветвей сокращает перебор | ||
| - Фактическое количество рекурсивных вызовов меньше N! | ||
| - Проверка валидности за O(N) на каждом уровне | ||
|
|
||
| **Применение:** Работает для N ≤ 15-20 за нормальное время | ||
|
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. Вы уверены, что оно будет работать для 20?... |
||
|
|
||
| ## 3. Простое решение с множествами | ||
|
|
||
| **Сложность:** O(N!) | ||
|
|
||
| **Обоснование:** | ||
| - Теоретическая сложность остается O(N!) | ||
| - Проверка конфликтов через множества работает за O(1) | ||
| - Немного медленнее из-за работы с множествами | ||
|
|
||
| **Применение:** Работает для N ≤ 15-18 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| def is_valid_recursive(board, row, col): | ||
| # проверяем, можно ли поставить ферзя на позицию (row, col) | ||
| for i in range(row): | ||
| # проверка столбца и диагоналей | ||
| if board[i] == col or abs(board[i] - col) == abs(i - row): | ||
| return False | ||
| return True | ||
|
|
||
| def solve_recursive(n, row, board, solutions): | ||
| # рекурсивно находит все решения | ||
| if row == n: | ||
| solutions.append(board) | ||
|
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 | ||
|
|
||
| for col in range(n): | ||
| if is_valid_recursive(board, row, col): | ||
| board[row] = col | ||
| # возвращаемся к 1 строке и смотрим следующий столбец | ||
| solve_recursive(n, row + 1, board, solutions) | ||
|
|
||
| def queens_recursive(n): | ||
| # запускаем решение | ||
| if n < 1: | ||
| return 0 | ||
|
|
||
| solutions = [] | ||
| board = [-1] * n # board[i] = столбец ферзя в строке i | ||
| solve_recursive(n, 0, board, solutions) | ||
| return len(solutions) | ||
|
|
||
| # тест | ||
| for n in range(1, 11): | ||
| print(f"n={n}: {queens_recursive(n)} решений") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| def backtrack(row, columns, diagonal1, diagonal2): | ||
| if row == 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. Переменная |
||
| return 1 | ||
|
|
||
| count = 0 | ||
| for col in range(n): | ||
| # вычисляем номера диагоналей | ||
| d1 = row - col # диагональ \ | ||
| d2 = row + col # диагональ / | ||
|
|
||
| # проверяем конфликты | ||
| if col in columns or d1 in diagonal1 or d2 in diagonal2: | ||
| continue | ||
|
|
||
| # добавляем ферзя | ||
| columns.add(col) | ||
| diagonal1.add(d1) | ||
| diagonal2.add(d2) | ||
|
|
||
| # рекурсивный вызов | ||
| count += backtrack(row + 1, columns, diagonal1, diagonal2) | ||
|
|
||
| # убираем ферзя (откат) | ||
| columns.remove(col) | ||
| diagonal1.remove(d1) | ||
| diagonal2.remove(d2) | ||
|
|
||
| return count | ||
|
|
||
|
|
||
| def queens_simple(n): | ||
| # рекурсивное решение с множествами | ||
| if n < 1: | ||
| return 0 | ||
|
|
||
| return backtrack(0, set(), set(), set()) | ||
|
|
||
|
|
||
| # тест | ||
| for n in range(1, 11): | ||
| print(f"n={n}: {queens_simple(n)} решений") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import itertools | ||
|
|
||
| def is_valid_bruteforce(board): | ||
| # проверяет, можно ли так поставить ферзей | ||
| n = len(board) | ||
| for i in range(n): | ||
| for j in range(i + 1, n): | ||
| # проверка на одну диагональ | ||
| if abs(i - j) == abs(board[i] - board[j]): | ||
| return False | ||
| return True | ||
|
|
||
| def queens_bruteforce(n): | ||
| # перебор всех возможных расстановок | ||
| if n < 1 or n > 10: # ограничение из-за сложности | ||
| return 0 | ||
|
|
||
| count = 0 | ||
| # генерируем все перестановки (каждый ферзь в уникальной строке и столбце) | ||
| for permutation in itertools.permutations(range(n)): | ||
| if is_valid_bruteforce(permutation): | ||
| count += 1 | ||
| return count | ||
|
|
||
|
|
||
| # тест | ||
| for n in range(1, 11): | ||
| print(f"n={n}: {queens_bruteforce(n)} решений") |
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.
Для написания формул можно использовать $$:$N! \cdot N^2$