Как узнать
перечислить все подмножества, перестановки или сочетания, или расставить что-то по правилам (ферзи, судоку); ввод маленький, часто n ≤ 20.
Как решать такие задачи
- Определи состояние: что уже выбрано и что осталось решить.
- Перечисли варианты на каждом шаге. Отбрось те, что нарушают правила.
- Для каждого варианта: выбери его, иди глубже, потом отмени выбор.
- Когда решать больше нечего, сохрани копию пути.
Вариант: Перестановки
То же, но выбираем, какое число поставить следующим, из ещё не занятых. Отмена выбора освобождает число для следующей ветки.
- Держи рядом с path массив used: used[i] равен true, пока nums[i] стоит в path.
- В каждом вызове пробуй каждый индекс, у которого used — false: отметь его и добавь число, иди глубже, потом убери число и сними отметку.
- Когда в path все n чисел, сохрани копию.
- В сочетаниях порядок не важен: передавай начальный индекс и пробуй только с него и дальше (Combinations, Combination Sum).
- Отрезай ветку, как только счётчик говорит, что она не сработает: ")" не больше, чем "(" (Generate Parentheses), один ферзь на строку, столбец и диагональ (N-Queens).
Вариант: Путь по сетке
То же, но путь идёт по сетке. Клетки на пути помечаем, чтобы не наступить на них дважды, а в тупике снимаем пометку, чтобы через клетку мог пройти другой путь.
- Запускай поиск из каждой клетки с первой буквой.
- В вызове: если это последняя буква, верни true. Иначе пометь клетку (замени её на # или храни множество занятых).
- Перебери четырёх соседей: иди глубже только в того, где стоит следующая буква. Если вызов ниже вернул true, сразу верни true.
- Если ни один сосед не подошёл, сними пометку и верни false, чтобы клетку могли взять другие пути.
- Если слов много, ищи по префиксному дереву (trie) этих слов: один обход сетки ведёт сразу все слова с текущим префиксом (Word Search II).
Где встречается
- Регулярные выражения. Движки регулярных выражений в Python, Perl и PCRE пробуют один вариант совпадения, а если дальше не сходится, откатываются и пробуют следующий. Поэтому неудачное выражение может работать очень долго.
- Установка пакетов. dnf и zypper подбирают версии пакетов SAT-решателем (libsolv): он выбирает версию, а при конфликте отменяет выбор и пробует другую.
- Пролог. Программа на Прологе сама перебирает варианты с возвратом: если правило не сработало, исполнитель возвращается к последнему выбору и пробует следующий вариант.