Генерация всех правильных скобочных последовательностей: различия между версиями

Материал из Algocode wiki
Перейти к: навигация, поиск
(Новая страница: «= Задача = По данному $n$ надо вывести все правильные скобочные последовательности из $n$ па...»)
 
 
(не показаны 3 промежуточные версии этого же участника)
Строка 1: Строка 1:
 
= Задача =
 
= Задача =
По данному $n$ надо вывести все правильные скобочные последовательности из $n$ пар скобок в лексикографическом порядке. Например, если $n = 2$, надо вывести
+
По данному $n$ надо вывести все правильные скобочные последовательности из $n$ пар скобок в лексикографическом порядке. Например, если $n = 3$, надо вывести
# (())
+
#((()))
# ()()
+
#(()())
 +
#(())()
 +
#()(())
 +
#()()()
  
 
= Рекурсивный перебор =
 
= Рекурсивный перебор =
Строка 10: Строка 13:
  
 
<syntaxhighlight lang="C++">
 
<syntaxhighlight lang="C++">
void gen(int n, vector<char>& cur_seq, int cur_balance=0 int cur_index=0) {
+
void gen(int n, vector<char>& cur_seq, int cur_balance=0, int cur_index=0) {
   if (cur_pos == 2 * n) {
+
   if (cur_index == 2 * n) {
 
     for (auto& bracket : cur_seq) {
 
     for (auto& bracket : cur_seq) {
 
       cout << bracket;
 
       cout << bracket;
Строка 17: Строка 20:
 
     cout << endl;
 
     cout << endl;
 
   } else {
 
   } else {
     if (cur_balance == cur_seq.size() - cur_pos) {  
+
     if (cur_balance == 2 * n - cur_index) {
 
         // если количество оставшихся позиций в точности равно
 
         // если количество оставшихся позиций в точности равно
 
         // количеству скобок, которые надо закрыть, то новые скобки мы не можем открывать
 
         // количеству скобок, которые надо закрыть, то новые скобки мы не можем открывать
Строка 23: Строка 26:
 
         cur_seq[cur_index] = ')';
 
         cur_seq[cur_index] = ')';
 
         cur_balance--;
 
         cur_balance--;
 
+
        gen(n, cur_seq, cur_balance, cur_index + 1);
 
     } else {
 
     } else {
 
         // пробуем поставить обе скобки, сначала ставим ту,
 
         // пробуем поставить обе скобки, сначала ставим ту,
Строка 32: Строка 35:
 
         gen(n, cur_seq, cur_balance, cur_index + 1);
 
         gen(n, cur_seq, cur_balance, cur_index + 1);
  
         cur_seq[cur_index] = ')';
+
         if (cur_balance > 1) {
        cur_balance-=2;
+
            cur_seq[cur_index] = ')';
        gen(n, cur_seq, cur_balance, cur_index + 1);
+
            cur_balance -= 2;
 +
            gen(n, cur_seq, cur_balance, cur_index + 1);
 +
      }
 
     }
 
     }
 
   }
 
   }
Строка 40: Строка 45:
  
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
{{Автор|Александр Гришутин|rationalex}}
 +
 +
[[Категория:Конспект]]

Текущая версия на 21:24, 8 мая 2020

Задача

По данному $n$ надо вывести все правильные скобочные последовательности из $n$ пар скобок в лексикографическом порядке. Например, если $n = 3$, надо вывести

  1. ((()))
  2. (()())
  3. (())()
  4. ()(())
  5. ()()()

Рекурсивный перебор

Давайте напишем следующую процедуру


void gen(int n, vector<char>& cur_seq, int cur_balance=0, int cur_index=0) {
  if (cur_index == 2 * n) {
    for (auto& bracket : cur_seq) {
       cout << bracket;
    }
    cout << endl;
  } else {
    if (cur_balance == 2 * n - cur_index) {
        // если количество оставшихся позиций в точности равно
        // количеству скобок, которые надо закрыть, то новые скобки мы не можем открывать

        cur_seq[cur_index] = ')';
        cur_balance--;
        gen(n, cur_seq, cur_balance, cur_index + 1);
    } else {
        // пробуем поставить обе скобки, сначала ставим ту,
        // которая лексикографически меньше

        cur_seq[cur_index] = '(';
        cur_balance++;
        gen(n, cur_seq, cur_balance, cur_index + 1);

        if (cur_balance > 1) {
            cur_seq[cur_index] = ')';
            cur_balance -= 2;
            gen(n, cur_seq, cur_balance, cur_index + 1);
       }
    }
  }
}



Автор конспекта: Александр Гришутин

По всем вопросам пишите в telegram @rationalex