ЗАДАЧИ
problems.ru |
О проекте
|
Об авторах
|
Справочник
Каталог по темам | по источникам | |
|
Задача 98835
УсловиеНапечатать все перестановки чисел 1..n так, чтобы каждая следующая получалась из предыдущей перестановкой (транспозицией) двух соседних чисел. Например, при n=3 допустим такой порядок:
3.2 1 2 3.1 2.1 3 1 2.3
1.3 2 3 1 2
(между переставляемыми числами вставлены точки).
РешениеНаряду с множеством перестановок рассмотрим множество последовательностей y[1]..y[n] целых неотрицательных чисел, для которых
i позиция числа i в перестановке,
--е обратное к перестановке отображение,
и соответствующим образом её корректировать. Вот какая
получается программа:
program test; | const n=...; | var | x: array [1..n] of 1..n; {перестановка} | inv_x: array [1..n] of 1..n; {обратная перестановка} | y: array [1..n] of integer; {y[i] < i} | d: array [1..n] of -1..1; {направления} | b: boolean; | | procedure print_x; | | var i: integer; | begin | | for i:=1 to n do begin | | | write (x[i], ' '); | | end; | | writeln; | end; | | procedure set_first;{первая: y[i]=0 при всех i} | | var i : integer; | begin | | for i := 1 to n do begin | | | x[i] := n + 1 - i; | | | inv_x[i] := n + 1 - i; | | | y[i]:=0; | | | d[i]:=1; | | end; | end; | | procedure move (var done : boolean); | | var i, j, pos1, pos2, val1, val2, tmp : integer; | begin | | i := n; | | while (i > 1) and (((d[i]=1) and (y[i]=i-1)) or | | | ((d[i]=-1) and (y[i]=0))) do begin | | | i := i-1; | | end; | | done := (i>1); {упрощение: первый член нельзя менять} | | if done then begin | | | y[i] := y[i]+d[i]; | | | for j := i+1 to n do begin | | | | d[j] := -d[j]; | | | end; | | | pos1 := inv_x[i]; | | | val1 := i; | | | pos2 := pos1 + d[i]; | | | val2 := x[pos2]; | | | {pos1, pos2 - номера переставляемых элементов; | | | val1, val2 - их значения; val2 < val1} | | | tmp := x[pos1]; | | | x[pos1] := x[pos2]; | | | x[pos2] := tmp; | | | tmp := inv_x[val1]; | | | inv_x[val1] := inv_x[val2]; | | | inv_x[val2] := tmp; | | end; | end; | begin | set_first; | print_x; | b := true; | {напечатаны все перестановки до текущей включительно; | если b ложно, то текущая - последняя} | while b do begin | | move (b); | | if b then print_x; | end; end. Источники и прецеденты использования |
© 2004-...
МЦНМО
(о копирайте)
|
Пишите нам
|