Программа курса:
Разбор задачи: Красивая композиция
Предложенный нами код решения:
def count_arrangement(n):
# Функция для подсчета прекрасных перестановок
def backtrack(index, used):
# Если достигнут конец, найдено решение
if index > n:
return 1
count = 0
for num in range(1, n + 1):
if not used[num] and (num % index == 0 or index % num == 0):
used[num] = True
count += backtrack(index + 1, used)
used[num] = False
return count
# Используется для отслеживания занятых чисел
used = [False] * (n + 1)
return backtrack(1, used)Рассмотрим решение задачи о подсчете "прекрасных перестановок" пошагово.
1. Определение функции
def count_arrangement(n):
Функция принимает целое число n — размер множества чисел от 1 до n, для которых требуется найти количество "прекрасных перестановок".
2. Вложенная функция для поиска перестановок
def backtrack(index, used):
Вложенная функция backtrack выполняет перебор перестановок.
indexуказывает текущую позицию в перестановке.used— список, отслеживающий, какие числа уже заняты (Trueозначает, что число используется).
3. Базовый случай
if index > n:
return 1
Если текущая позиция index превышает n, это означает, что перестановка успешно сформирована, и её можно считать "прекрасной". В этом случае функция возвращает 1, добавляя к общему количеству найденных перестановок.
4. Перебор возможных чисел
for num in range(1, n + 1):
Этот цикл перебирает все числа от 1 до n. Каждое число num проверяется, можно ли его использовать на текущей позиции index.
5. Проверка условий
if not used[num] and (num % index == 0 or index % num == 0):
Число num можно использовать на позиции index, если оно:
- Ещё не занято (
not used[num]). - Удовлетворяет условию задачи:
numделится наindex.- Либо
indexделится наnum.
Если оба условия выполнены, мы можем продолжить с этим числом.
6. Пометка числа как используемого
used[num] = True
count += backtrack(index + 1, used)
used[num] = False
- Число
numпомечается как занятое (True). - Рекурсивно вызывается
backtrackдля следующей позиции (index + 1). - После завершения текущего вызова число освобождается (
False), чтобы его можно было использовать в других перестановках.
7. Возврат итогового значения
return count
Счётчик count аккумулирует количество "прекрасных перестановок", найденных для текущей ветки рекурсии.
8. Инициализация и запуск рекурсии
used = [False] * (n + 1)
return backtrack(1, used)
Список used создаётся с размером n + 1 (индексация начинается с 1). Все элементы инициализируются как False, так как на старте ни одно число не используется.
Рекурсия запускается с начальной позиции index = 1.
Пример работы
Для n = 2:
index = 1, перебираются числа{1, 2}:- Для
num = 1, условие выполнено. Рекурсия продолжается сindex = 2. - Для
num = 2, условие выполнено. Рекурсия продолжается сindex = 2.
- Для
index = 2, перебираются оставшиеся числа:- Для первого вызова (
num = 1), остаётсяnum = 2, и условие выполнено. - Для второго вызова (
num = 2), остаётсяnum = 1, и условие выполнено.
- Для первого вызова (
Итог: 2 перестановки.