This commit is contained in:
krahets
2026-04-03 18:46:15 +08:00
parent 377736b1bd
commit 9d21ca86b0
352 changed files with 46563 additions and 11262 deletions
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -18,5 +18,5 @@ icon: material/map-marker-path
- [13.1   Алгоритм поиска с возвратом](backtracking_algorithm.md)
- [13.2   Задача о перестановках](permutations_problem.md)
- [13.3   Задача о сумме подмножеств](subset_sum_problem.md)
- [13.4   Задача о $n$ ферзях](n_queens_problem.md)
- [13.4   Задача о n ферзях](n_queens_problem.md)
- [13.5   Резюме](summary.md)
@@ -8,7 +8,7 @@ comments: true
Согласно правилам шахмат ферзь может атаковать фигуры, находящиеся с ним на одной строке, в одном столбце или на одной диагонали. Даны $n$ ферзей и шахматная доска размера $n \times n$ ; требуется найти такие расстановки, при которых ни одна пара ферзей не может атаковать друг друга.
Как показано на рисунке 13-15, при $n = 4$ существует два решения. С точки зрения backtracking доска размера $n \times n$ содержит $n^2$ клеток, которые образуют все возможные выборы `choices` . По мере поочередного размещения ферзей состояние доски непрерывно меняется, и текущее содержимое доски образует состояние `state` .
Как показано на рисунке 13-15, при $n = 4$ существует два решения. С точки зрения поиска с возвратом доска размера $n \times n$ содержит $n^2$ клеток, которые образуют все возможные выборы `choices` . По мере поочередного размещения ферзей состояние доски непрерывно меняется, и текущее содержимое доски образует состояние `state` .
![Решения задачи о 4 ферзях](n_queens_problem.assets/solution_4_queens.png){ class="animation-figure" }
@@ -26,9 +26,9 @@ comments: true
Дан массив целых чисел, в котором нет повторяющихся элементов. Верните все возможные перестановки.
С точки зрения backtracking **процесс построения перестановок можно представить как результат последовательности выборов**. Пусть входной массив равен $[1, 2, 3]$ ; если мы сначала выберем $1$ , затем $3$ , а потом $2$ , то получим перестановку $[1, 3, 2]$ . Откат означает отмену одного из выборов с последующей попыткой других вариантов.
С точки зрения поиска с возвратом **процесс построения перестановок можно представить как результат последовательности выборов**. Пусть входной массив равен $[1, 2, 3]$ ; если мы сначала выберем $1$ , затем $3$ , а потом $2$ , то получим перестановку $[1, 3, 2]$ . Откат здесь означает отмену одного из выборов с последующей попыткой других вариантов.
С точки зрения кода backtracking множество кандидатов `choices` состоит из всех элементов входного массива, а состояние `state` - из элементов, уже выбранных к текущему моменту. Обратите внимание, что каждый элемент разрешено выбирать только один раз, **поэтому все элементы в `state` должны быть уникальны**.
С точки зрения кода поиска с возвратом множество кандидатов `choices` состоит из всех элементов входного массива, а состояние `state` - из элементов, уже выбранных к текущему моменту. Поскольку каждый элемент разрешено выбирать только один раз, **все элементы в `state` должны быть уникальны**.
Как показано на рисунке 13-5, процесс поиска можно развернуть в дерево рекурсии, где каждый узел представляет текущее состояние `state` . Начиная от корня, после трех раундов выбора мы попадаем в листья, и каждый лист соответствует одной перестановке.
@@ -53,7 +53,7 @@ comments: true
### 2.   Реализация кода
После прояснения всей логики можно просто "заполнить пропуски" в шаблоне backtracking. Чтобы сократить общий объем кода, мы не будем отдельно реализовывать каждую функцию из каркаса, а раскроем их прямо внутри `backtrack()` :
После прояснения всей логики можно просто "заполнить пропуски" в шаблоне поиска с возвратом. Чтобы сократить общий объем кода, мы не будем отдельно реализовывать каждую функцию из каркаса, а раскроем их прямо внутри `backtrack()` :
=== "Python"
@@ -565,7 +565,7 @@ comments: true
Точно так же, если в первом раунде выбрать $2$ , то во втором раунде выборы $1$ и $\hat{1}$ снова создадут дублирующиеся ветви, поэтому и в этом случае ветвь $\hat{1}$ нужно отсечь.
По своей сути **наша цель заключается в том, чтобы на каждом раунде выбора каждый из нескольких равных элементов выбирался только один раз**.
Иначе говоря, **наша цель заключается в том, чтобы на каждом раунде выбора каждый из нескольких равных элементов выбирался только один раз**.
![Обрезка повторяющихся перестановок](permutations_problem.assets/permutations_ii_pruning.png){ class="animation-figure" }
File diff suppressed because one or more lines are too long
+8 -8
View File
@@ -7,21 +7,21 @@ comments: true
### 1.   Ключевые выводы
- Алгоритм поиска с возвратом по своей сути является методом полного перебора: он ищет решения путем обхода пространства решений в глубину. Во время поиска он фиксирует решения, удовлетворяющие условиям, пока не найдет все такие решения или пока обход не завершится.
- Процесс backtracking состоит из двух частей: попытки и отката. Он с помощью поиска в глубину пробует разные варианты выбора; когда встречается состояние, не удовлетворяющее ограничениям, алгоритм отменяет предыдущий выбор, возвращается к прошлому состоянию и продолжает пробовать другие варианты. Попытка и откат являются двумя противоположными по направлению действиями.
- Задачи backtracking обычно содержат несколько ограничений, которые можно использовать для обрезки. Обрезка позволяет заранее завершать ненужные ветви поиска и тем самым значительно повышать эффективность.
- Алгоритм backtracking в первую очередь применяется для решения поисковых задач и задач с ограничениями. Задачи комбинаторной оптимизации тоже можно решать с его помощью, но для них часто существуют более эффективные или более подходящие методы.
- Процесс поиска с возвратом состоит из двух частей: попытки и отката. Он с помощью поиска в глубину пробует разные варианты выбора; когда встречается состояние, не удовлетворяющее ограничениям, алгоритм отменяет предыдущий выбор, возвращается к прошлому состоянию и продолжает пробовать другие варианты. Попытка и откат являются двумя противоположными по направлению действиями.
- Задачи поиска с возвратом обычно содержат несколько ограничений, которые можно использовать для обрезки. Обрезка позволяет заранее завершать ненужные ветви поиска и тем самым значительно повышать эффективность.
- Алгоритм поиска с возвратом в первую очередь применяется для решения поисковых задач и задач с ограничениями. Задачи комбинаторной оптимизации тоже можно решать с его помощью, но для них часто существуют более эффективные или более подходящие методы.
- Задача о перестановках нацелена на поиск всех возможных перестановок элементов данного множества. Мы используем массив для записи того, был ли выбран каждый элемент, и отсекаем ветви, где один и тот же элемент выбирается повторно, чтобы гарантировать однократный выбор каждого элемента.
- В задаче о перестановках, если во множестве присутствуют повторяющиеся элементы, в итоговом результате возникнут повторяющиеся перестановки. Поэтому нужно ограничить выбор равных элементов так, чтобы в каждом раунде каждый из них выбирался только один раз; обычно это реализуется с помощью хеш-множества.
- Цель задачи о сумме подмножеств - найти все подмножества данного множества, сумма которых равна целевому значению. В множестве порядок элементов не важен, однако процесс поиска порождает результаты во всех возможных порядках, из-за чего появляются повторяющиеся подмножества. Поэтому перед запуском backtracking мы сортируем данные и вводим переменную, указывающую начальную точку обхода в каждом раунде, чтобы отсечь ветви, создающие дубликаты.
- Цель задачи о сумме подмножеств - найти все подмножества данного множества, сумма которых равна целевому значению. В множестве порядок элементов не важен, однако процесс поиска порождает результаты во всех возможных порядках, из-за чего появляются повторяющиеся подмножества. Поэтому перед запуском поиска с возвратом мы сортируем данные и вводим переменную, указывающую начальную точку обхода в каждом раунде, чтобы отсечь ветви, создающие дубликаты.
- В задаче о сумме подмножеств равные элементы массива также порождают повторяющиеся множества. При наличии предварительной сортировки их можно отсекать, проверяя равенство соседних элементов, и тем самым гарантировать, что в каждом раунде равные элементы будут выбираться только один раз.
- Задача о $n$ ферзях состоит в поиске способов разместить $n$ ферзей на доске размера $n \times n$ так, чтобы никакие два ферзя не атаковали друг друга. Ограничения этой задачи включают строки, столбцы, главные диагонали и побочные диагонали. Чтобы выполнить ограничение по строкам, используется построчная стратегия размещения, гарантирующая по одному ферзю в каждой строке.
- Обработка ограничений по столбцам и диагоналям устроена похожим образом. Для ограничения по столбцам используется массив, фиксирующий наличие ферзя в каждом столбце. Для диагоналей используются два массива, записывающие наличие ферзей на главных и побочных диагоналях. Основная сложность здесь состоит в том, чтобы найти закономерность индексов строк и столбцов клеток, лежащих на одной и той же главной или побочной диагонали.
### 2.   Q & A
### 2.   Вопросы и ответы
**Q**: Как понять связь между поиском с возвратом и рекурсией?
В целом backtracking - это скорее "алгоритмическая стратегия", а рекурсия больше похожа на "инструмент".
В целом поиск с возвратом - это скорее "алгоритмическая стратегия", а рекурсия больше похожа на "инструмент".
- Алгоритмы поиска с возвратом обычно реализуются на основе рекурсии. Однако backtracking - это лишь один из вариантов применения рекурсии, а именно ее использование в поисковых задачах.
- Структура рекурсии отражает парадигму разбиения на подзадачи и часто применяется для решения задач divide and conquer, backtracking, динамического программирования (мемоизированной рекурсии) и других подобных задач.
- Алгоритмы поиска с возвратом обычно реализуются на основе рекурсии. Однако поиск с возвратом - это лишь один из вариантов применения рекурсии, а именно ее использование в поисковых задачах.
- Структура рекурсии отражает парадигму разбиения на подзадачи и часто применяется для решения задач "разделяй и властвуй", поиска с возвратом, динамического программирования (мемоизированной рекурсии) и других подобных задач.