Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2002.12.12;
Скачать: [xml.tar.bz2];

Вниз

Очередная несложная задачка для разминки;)   Найти похожие ветки 

 
MBo   (2002-11-21 10:03) [0]

Найти количество S пpавильных скобочных последовательностей длины 2N (1<=N<=30)
Пpимеp: 2N=6:
((())), (()()), ()()(), (())(), ()(())
S= 5

Задача, естественно, не в нахождении формулы, а в составлении алгоритма программы

(взято с fido.ru.algoritms)


 
McSimm   (2002-11-21 10:43) [1]

Очевидное решение - рекурсивно.
Может есть неочевидное и более простое?


 
MBo   (2002-11-21 10:45) [2]

я тоже рекурсивно делал, без рекурсии пока не пробовал


 
Igorek   (2002-11-21 10:49) [3]


> MBo © (21.11.02 10:03)

На выходные надо задавать, когда время есть. А то работа еще...
:-)


 
Igorek   (2002-11-21 10:52) [4]


> McSimm © (21.11.02 10:43)
> Очевидное решение - рекурсивно.
> Может есть неочевидное и более простое?

В любом случае алгоритм аналогичный рекурсивному. Можно через стек. Также можно дать рекурентную формулу.


 
Alx2   (2002-11-21 11:53) [5]

Хм... :))


function sCount(stop, sum: integer): Integer;
begin
if stop = 0 then
Result := cardinal(sum=0)
else
begin
Result := sCount(stop - 1, sum + 1);
if sum > 0 then
inc(Result, sCount(stop - 1, sum - 1));
end;
end;
begin
ShowMessage(IntToStr(sCount(6 {длина последовательности}, 0)));
end;


 
Оливейра   (2002-11-21 12:56) [6]

На CBOSS.ru такую х... на тестовом задании предлагают, только на голых сях. В общем-то нерекурсивно даже проще - ищется первая открывающая скобка, копируется указатель на нее, во вложенном втором цикле ищется, начиная с этого указателя, закрывающая и подсчитывается количество открывающих и закрывающих скобок, найденных попутно. Если найдена закрывающая и число найденных открывающих равно числу закрывающих (0-0, 1-1 и т.п.) значит, найдена парная.


 
Alx2   (2002-11-21 13:44) [7]

>Оливейра © (21.11.02 12:56)
"Найти количество S пpавильных скобочных последовательностей длины 2N (1<=N<=30)
Пpимеp: 2N=6:
((())), (()()), ()()(), (())(), ()(())
S= 5"


 
MBo   (2002-11-21 13:45) [8]

>Alx2
отлично

>Оливейра
Это другая задача - в твоей нужно проверить сбалансированность скобок в выражении, решается прямым однопроходным прогоном, а здесь нужно кратчайшим способом перечислить все правильные комбинации


 
down   (2002-11-21 13:50) [9]

2Alx2
Можно пояснить, как работает?


 
MBo   (2002-11-21 13:57) [10]

мой вариант

procedure TForm1.Button1Click(Sender: TObject);
var
nmax, nhalf, NVar: integer;
s: string;

procedure AddSkobka(n, nl, right: integer);
begin
s[n * 2] := Chr(Ord("(") + right);
if right = 0 then
inc(nl);
if n = nmax then
begin
Memo1.Lines.Add(s);
inc(NVar);
Exit;
end;
if 2 * nl > n then
//если левых больше, чем правых, можно добавить правую
AddSkobka(n + 1, nl, 1);
if nl < nhalf then
//если левых половина общего количества, перестаем их добавлять
AddSkobka(n + 1, nl, 0);
end;

begin
nhalf := 4;
nmax := nhalf *2;
nvar := 0;
s := StringOfChar(" ", 2 * nmax);
AddSkobka(1, 0, 0);
Memo1.Lines.Add(IntToStr(NVar));
end;


 
MBo   (2002-11-21 14:03) [11]

решение задачи Оливейры
функция считает макс. глубину вложения, выдавая 255 для случая дисбаланса

function skobki(st:string):byte;
var i,j,max:byte;
begin
max:=0;
j:=0;
for i:=1 to length(st) do begin
if st[i]="(" then inc(j);
if st[i]=")" then dec(j);
if max<j then max:=j;
end;
if j<>0 then
max:=255;
Result:=max;
end;


 
MBo   (2002-11-21 15:08) [12]

пардон, последний постинг неправильный. Так вернее:

procedure TForm1.Button5Click(Sender: TObject);

function VernyeSkobki(st:string):Boolean;
var i,j:byte;
begin
Result:=False;
j:=0;
for i:=1 to length(st) do begin
if st[i]="(" then inc(j);
if st[i]=")" then
if j>0 then
dec(j)
else
Exit;
end;
Result:=j=0;
end;

begin
If VernyeSkobki("(()())") then
ShowMessage("OK")
else
ShowMessage("Fignya");
end;


 
Alx2   (2002-11-21 15:42) [13]

>MBo © (21.11.02 13:57)

Вот с выдачей результатов:


function RunProcess(Dimension: Integer): integer;
var S: string;
function sCountWithResult(stop, sum: integer): Integer;
begin
if stop = 0 then
if sum = 0 then
begin
Result := 1;
Memo1.Lines.Add(S)
end
else Result := 0
else
begin
S[Stop] := ")";
Result := sCountWithResult(stop - 1, sum + 1);
if sum > 0 then
begin
S[Stop] := "(";
inc(Result, sCountWithResult(stop - 1, sum - 1));
end;
end;
end;

begin
SetLength(S, Dimension);
Result := sCountWithResult(Dimension, 0);
end;

begin
RunProcess(6);
end;


 
MBo   (2002-11-21 15:46) [14]

>Alx2
Угу. Но главное- алгоритм, маленький и симпатичный ;)


 
Alx2   (2002-11-21 15:51) [15]

>down (21.11.02 13:50)
>Можно пояснить, как работает?

Можно, конечно.
Если представить заполняемую скобками последовательность как последовательность элементов "-1" и "1", где "-1" означает закрывающую скобку, а "1" - открывающую скобку, то для того, чтобы соблюсти правильность парности скобок, достаточно потребовать, чтобы сумма элементов по мере заполнения массива никогда не была меньше нуля. Отсюда следует условие
if sum > 0 then
.....

Остальное - простая рекурсия :)


 
down   (2002-11-21 16:23) [16]

Понятно, спасибо! Красиво, черт побери!


 
Alx2   (2002-11-21 16:27) [17]

>down (21.11.02 16:23)

:)


 
Igorek   (2002-11-22 10:30) [18]


> Alx2 © (21.11.02 16:27)

А еще полный перебор можно представить в виде бинарного дерева, где каждый узел имеет суму предыдущих и свое число (1 или -1). В данном случае реализован метод ветвей и границ - поиск обрывается при отрицательной сумме.
Но вот нерекурентную простую формулу не могу найти. :-(
Еще подумаю.



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2002.12.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.005 c
1-36111
KMI
2002-12-03 11:19
2002.12.12
Как создать текстовый файл в DOS-кодировке?


1-36212
AlexT1000
2002-11-29 14:08
2002.12.12
Как юзая FrameRgn отрисовывать выделение как в PhotoShop?


1-36208
^Sanya
2002-12-01 14:52
2002.12.12
TMemo or TRichEdit:


14-36362
Юрий К
2002-11-19 21:41
2002.12.12
Горы баксов в InterNet... достали письма


1-36154
LORD
2002-12-03 19:09
2002.12.12
Buffer + Tstream





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский