Rambler's Top100

Размещения. Перестановки. Сочетания

Имеется n различных предметов. Сколько из них можно составить k-расстановок? При этом две расстановки считаются различными, если они либо отличаются друг от друга хотя бы одним элементом, либо состоят из одних и тех же элементов, но расположенных в разном порядке.  Такие расстановки называют размещениями без повторений.

Размещением элементов из множества Е={а1,...,аn} по k называется упорядоченное подмножество из k элементов, принадлежащих Е.

Например: Дано множество Е={a1,a2,a3}.Найти размещения из Е по 2 элемента.

Получаем:

(a1,a2);(a2,a1);(a1,a3);(a3,a1);(a2,a3);(a3,a2).

Число размещений обозначают Аnk.

При составлении k размещений без повторений из n предметов нам надо сделать k выборов. На первом шаге можно выбрать любой из n предметов. На втором шаге выбрать из оставшихся n-1 предметов - ведь повторять сделанный выбор нельзя. На третьем шаге для выбора остается лишь n-2 свободных предметов, на четвертом n-3 предметов... на k-м шаге выбираем из n-k+1 предметов. Получаем, что число k - размещений без повторений из n предметов выражается следующим образом:

Ank   =n(n-1)...(n-k+1).

Еще эту формулу можно записать следующим образом:

Ank =n! / (n-k)!

Размещение с повторениями из n элементов множества Е={a1,a2,...,an} по k - всякая конечная последовательность, состоящая из k членов данного множества Е. Два размещения с повторениями считаются различными, если хотя бы на одном месте они имеют различные элементы множества Е. Число различных размещений с повторениями из n по k равно nk.

Вверх

Задача 1. Напечатать все последовательности длины k из чисел 1..n.

Решение: Будем печатать их в лексикографическом порядке (последовательность а предшествует последовательности b, если для некоторого i их начальные отрезки длины i равны, а (i+1)-ый член последовательности а меньше). Первой будет последовательность <1,1,...,1>, последней - <n,n,...,n>. Будем хранить последнюю напечатанную последовательность в массиве x[1],..,x[k]. 

last[1],..,last[k] положим равным n.  Для того, чтобы перейти к следующей последовательности надо: двигаясь с конца последовательности, найти самый правый член, меньший n, увеличить его на 1, а идущие за ним члены положить равными 1.

Процедура print(x:massiv) - вывод последовательности.

Функция egual(x,last:massiv):boolean - сравнивает элементы массивов, если x<>last, то egual:=false иначе egual:=true.

for i:=1 to k do x[i]:=1;

print(x);

for i:=1 to k do last[i]:=n;

while not(equal(x,last)) do

     begin

          p:=k; 

          while not (x[p]<n) do p:=p-1; 

          x[p]:=x[p]+1; 

          for i:=p+1 to k do x[i]:=1; 

          print(x);

     end;

Перестановки из n элементов - частный случай размещения элементов из Е по k, при k=n.

Иными словами, перестановками называют размещения без повторений из n элементов, в которые входят все элементы. Можно также сказать, что перестановками из n элементов называют всевозможные n-расстановки, каждая из которых содержит все эти элементы по одному разу и которые отличаются друг от друга лишь порядком элементов.

Число перестановок вычисляется по формуле:

Pn=Ann=n·(n-1)·...·2·1=n!

 

Алгоритм генерации перестановок в лексикографическом порядке:

1. Просматриваем а1,...,аn с конца до тех пор, пока не попадется ai<ai+1. Если таковых нет, то генерация закончена.

2. Рассматриваем ai+1,ai+2,...,an. Найдем первый с конца am больший ai и поменяем их местами.

3. ai+1,ai+2,...,an переставим в порядке возрастания (для этого достаточно её переписать с конца).

4. Печатаем найденную перестановку.

5.   Возвращаемся к пункту 1.

Первой при этом будет перестановка <1,2,..,n>, последней - <n,..,2,1>.

Сочетания элементов из Е={a1,...,an} по k называется упорядоченное подмножество из k элементов, принадлежащих Е и отличающиеся друг то друга составом, но не порядком элементов.

Число сочетаний вычисляется по формулам: 

 C00   =Ck0=C0k=Ckk=1

Cnk =Cnk-1    + Cn-1k-1    или   Cnk = Ank / k! = n! / (n-k)! k!

Алгоритм генерации сочетаний  Cnk.

1. Для i:=1 до k ci:=i; печатаем ci,  для i=1..k.

2. С конца находим такое i, что ci<>n-k+i. Если такого i нет, то генерация сочетаний закончена.

3. ci:=ci+1; для m=i+1,i+2,...,k выполним cm:=c m-1 +1; выводим ci для i=1,...,k.

4. Возвращаемся к пункту 2.

Вверх

Задача 2. Перечислить все возрастающие последовательности длины k из чисел 1..n в лексикографическом порядке (все сочетания из n по k).

Например: при n=5, k=2 получаем:

12 13 14 15 23 24 25 34 35 45

 

Решение: Минимальной будет последовательность <1,2,...,k>, а максимальной - <n-k+1,...,n-1,n>. Каждый i-ый член последовательности можно увеличить, если он меньше   n-k+i. После увеличения i-го элемента все следующие должны возрастать с шагом 1 

      function poisk1(x:massiv):boolean;

var q:boolean;

       i:integer;

begin

    q:=false;

     for i:=m downto 1 do

     if x[i]<>n-m+i then q:=true; 

     poisk1:=q; 

end.

function poisk2(x:massiv):integer;

var i:integer;

begin

      i:=m;

      while not(x[i]<n-m+i) do

       i:=i-1; poisk2:=i; 

end;

Функции poisk1 и poisk2 организуют поиск i-го элемента, который нужно увеличить на 1 Процедура print печатает полученную последовательность.

for j:=1 to m do x[j]:=j;

print(x);

while poisk1(x) do

     begin

          k:=poisk2(x);

           x[k]:=x[k]+1;

           for j:=k+1 to m do

                x[j]:=x[j-1]+1; 

           print(x);

     end;

Вверх

Задача 3. Перечислить все разбиения целого положительного числа n на целые положительные слагаемые (разбиения, отличающиеся лишь порядком слагаемых, считаются за одно).

Например: n=4 разбиения 1+1+1+1, 2+1+1, 2+2, 3+1, 4.

 

Решение:

 

Договоримся, что

1) в разбиениях слагаемые идут в невозрастающем порядке,

2) сами разбиения мы перечисляем в лексикографическом порядке.

Разбиение храним в начале массива x[1]..x[n], при этом количество входящих в него чисел обозначим k. В начале x[1]=...=x[n]=1, k=n, в конце x[1]=n,k=1.  В каком случае x[i] можно увеличить, не меняя предыдущих?Во-первых, должно быть x[i-1]>x[i] или i=1. Во-вторых, i должно быть не последним элементом (увеличение i надо компенсировать уменьшением следующих). Увеличив i, все следующие элементы надо взять минимально возможными.

procedure print(x:massiv;m:integer);

    var i:integer;

    begin

          for i:=1 to m do

              write(x[i],' '); 

    end;

Begin

      for j:=1 to n do x[j]:=1;

          print(x,n);

      k:=n;

      while k<>1 do

      begin

           i:=k-1;

           while not((i=1) or (x[i-1]>x[i])) do

                i:=i-1;

            x[i]:=x[i]+1;

            sum:=0;

            for j:=i+1 to k do

                sum:=sum+x[j];

            for j:=1 to sum-1 do

                x[i+j]:=1; k:=i+sum-1; 

            print(x,k);

      end; 

end.

 

Упражнения.

1. Напечатать все размещения без повторений из чисел 1..n по k.

2. Напечатать все последовательности положительных целых чисел длины k, у которых i-ый член не превосходит i.

3. Напечатать все перестановки чисел 1..n (то есть последовательности длины n, в которые каждое из этих чисел входит по одному разу).

4. Перечислить все убывающие последовательности длины k из чисел 1..n в лексикографическом порядке (при n=5, k=2 получаем: 21 31 32 41 42 43 51 52 53 54).

5. Перечислить все разбиения целого положительного числа n на целые положительные слагаемые. Представляя разбиения как не возрастающие последовательности, перечислить их в порядке, обратном лексикографическому (для n=4, должно быть 4,3+1,2+2,2+1+1,1+1+1+1).

Вверх

Белорусский рейтинг MyMinsk.com Сайты беларуси Регистр "ЗУБР" Каталог на TIGA.BY, а также  новости, работа, объявления, фото и многое другое Рейтинг@Mail.ru Rambler's Top100 Белорусский каталог программ Faststart - рейтинг сайтов, каталог интернет ресурсов, счетчик посещаемос­ти Яндекс.Метрика
Hosted by uCoz