Открыть сервис

Backtracking

Backtracking (с англ. — «возврат назад», «откат») — это общий алгоритмический метод решения задач, основанный на последовательном построении решения с проверкой каждого шага на соответствие условиям задачи. Если текущий частичный вариант не может быть продолжен до полного решения, алгоритм отступает на один или несколько шагов назад (выполняет «откат») и пробует другой путь. Backtracking относится к классу методов перебора с возвратом и широко применяется в комбинаторике, искусственном интеллекте, теории игр и задачах оптимизации.

История

Метод backtracking имеет корни в математике и логике XIX века. Одним из первых известных примеров является задача о восьми ферзях, сформулированная в 1848 году немецким шахматистом Максом Безелем. В 1850 году Франц Наук предложил систематический перебор с возвратом для её решения. В 1950-х годах, с развитием вычислительной техники, метод стал формализоваться как алгоритмическая техника. Ключевой вклад внёс американский математик Деррик Генри Лемер, который в 1955 году описал общий алгоритм поиска с возвратом для решения комбинаторных задач. В 1960-х годах термин «backtracking» популяризировал Роберт Флойд, а в 1970-х годах метод был систематизирован в работах Никлауса Вирта и Дональда Кнута. С тех пор backtracking стал стандартным инструментом в курсах алгоритмов и структур данных.

Основные принципы

Backtracking основан на идее рекурсивного или итеративного перебора всех возможных вариантов решений, но с отсечением заведомо неперспективных ветвей. Алгоритм работает следующим образом:

  1. Построение частичного решения — на каждом шаге выбирается один из возможных вариантов, который добавляется к текущему частичному решению.
  2. Проверка ограничений — после добавления проверяется, удовлетворяет ли текущее состояние условиям задачи. Если нет — вариант отбрасывается, и происходит возврат.
  3. Рекурсивный спуск — если ограничения выполнены, алгоритм рекурсивно переходит к следующему шагу.
  4. Откат — если на каком-то этапе невозможно продолжить построение (нет допустимых вариантов или достигнут тупик), алгоритм возвращается на предыдущий шаг и пробует следующий вариант.
  5. Завершениепроцесс продолжается, пока не будет найдено одно или все возможные решения, либо не будет доказано отсутствие решений.

Ключевое свойство backtracking — использование отсечения (pruning): если текущее частичное решение не может быть расширено до полного, дальнейший перебор по этой ветви прекращается. Это отличает его от полного перебора (brute force) и делает метод эффективным для задач с большим пространством поиска.

Классификация

Backtracking можно классифицировать по нескольким признакам:

По типу решаемых задач

  • Задачи на нахождение одного решения — например, поиск пути в лабиринте.
  • Задачи на нахождение всех решений — например, все расстановки ферзей на шахматной доске.
  • Задачи на оптимизацию — поиск наилучшего решения (часто с использованием ветвей и границ).

По способу реализации

  • Рекурсивный backtracking — наиболее распространённый, использует стек вызовов для хранения состояний.
  • Итеративный backtracking — реализуется с помощью явного стека, что позволяет избежать переполнения стека при глубоком поиске.

По стратегии обхода

  • Поиск в глубину (DFS) — стандартный для backtracking, когда сначала исследуется одна ветвь до конца.
  • Поиск в ширину (BFS) — редко используется, так как требует больших затрат памяти.

Примеры задач

Задача о восьми ферзях

Классическая задача: расставить на шахматной доске 8×8 восемь ферзей так, чтобы они не атаковали друг друга. Алгоритм последовательно размещает ферзей на строках, проверяя, не бьёт ли новый ферзь уже поставленных. Если на очередной строке нет безопасной клетки, происходит откат.

Задача о сумме подмножеств

Дано множество чисел и целевая сумма. Необходимо найти подмножество, сумма элементов которого равна заданному числу. Алгоритм перебирает элементы, добавляя или не добавляя их в текущее подмножество, и отсекает ветви, если текущая сумма превышает целевую.

Поиск пути в лабиринте

Алгоритм пытается пройти от начальной точки до конечной, двигаясь по свободным клеткам. Если встречается тупик, происходит возврат к предыдущей развилке.

Судоку

Решение головоломки Судоку: алгоритм заполняет пустые клетки цифрами от 1 до 9, проверяя соответствие правилам (уникальность в строке, столбце и блоке). При нарушении — откат.

Применение

Backtracking используется в различных областях:

  • Комбинаторика — генерация перестановок, сочетаний, разбиений.
  • Искусственный интеллект — решение логических задач, планирование, системы поддержки принятия решений.
  • Теория игр — алгоритмы для игр с полной информацией (шахматы, шашки, крестики-нолики), где backtracking применяется для оценки ходов.
  • Криптография — взлом простых шифров методом перебора с отсечением.
  • Биоинформатика — выравнивание последовательностей ДНК и белков.
  • Робототехника — планирование траекторий движения в средах с препятствиями.

Преимущества и недостатки

Преимущества

  • Универсальность — применим к широкому классу задач.
  • Простота реализации — рекурсивная форма интуитивно понятна.
  • Гарантия нахождения решения — при наличии хотя бы одного решения алгоритм его найдёт.
  • Эффективность при хорошем отсечении — в задачах с сильными ограничениями перебор может быть сокращён в разы.

Недостатки

  • Экспоненциальная сложность — в худшем случае время работы растёт как O(2^n) или O(n!), что делает метод неприменимым для больших размерностей.
  • Зависимость от качества отсечения — без эффективного отсечения алгоритм вырождается в полный перебор.
  • Потребление памяти — при рекурсивной реализации стек вызовов может быть глубоким, что приводит к переполнению.

Сравнение с другими методами

МетодПринципСложностьОбласть применения
BacktrackingПеребор с возвратом и отсечениемЭкспоненциальная (в худшем)Комбинаторные задачи, головоломки
Полный перебор (brute force)Перебор всех вариантов без отсеченияЭкспоненциальнаяТолько для малых размерностей
Динамическое программированиеРазбиение на подзадачи с запоминаниемПолиномиальная (часто)Задачи с оптимальной подструктурой
Жадные алгоритмыЛокально оптимальный выборПолиномиальнаяЗадачи, где локальный оптимум глобален
Метод ветвей и границBacktracking с оценкой границЭкспоненциальная (в худшем)Оптимизационные задачи

Реализация

Пример рекурсивной реализации backtracking на псевдокоде для задачи о сумме подмножеств:

`` function backtrack(partial_sum, index, current_set): if partial_sum == target: print(current_set) return if index >= len(numbers) or partial_sum > target: return // Включить текущий элемент current_set.add(numbers[index]) backtrack(partial_sum + numbers[index], index + 1, current_set) current_set.remove(numbers[index]) // Исключить текущий элемент backtrack(partial_sum, index + 1, current_set) ``

Интересные факты

  • В 1972 году Эдсгер Дейкстра использовал backtracking для задачи о кратчайшем пути в графе с отрицательными весами, что привело к созданию алгоритма Беллмана — Форда.
  • Backtracking лежит в основе многих алгоритмов для решения головоломок, таких как «Ханойская башня» и «Кубик Рубика».
  • В 2010 году с помощью backtracking была решена задача о числе расстановок 27 ферзей на доске 27×27 — найдено ровно 234 907 967 154 122 528 решений.
  • Метод используется в компиляторах для синтаксического анализа (например, в рекурсивном спуске).

Источники

  • Д. Кнут. Искусство программирования. Том 4А. Комбинаторные алгоритмы. — М.: Вильямс, 2013.
  • Н. Вирт. Алгоритмы и структуры данных. — М.: Мир, 1989.
  • Т. Кормен, Ч. Лейзерсон, Р. Ривест, К. Штайн. Алгоритмы: построение и анализ. — М.: Вильямс, 2013.
  • Р. Седжвик. Фундаментальные алгоритмы на C++. — М.: ДиаСофт, 2002.
  • D. H. Lehmer. The machine tools of combinatorics // Applied Combinatorial Mathematics. — 1962.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →