Разбиения

Число разбиений (порядок записи подмножеств - элементов разбиения считаем значимым) n-элементного множества на k £ n непустых подмножеств равно:

.

Общее число разбиений:

.

[Донской В.И. Дискретная математика. Уч. пос. – Симферополь, "Сонат", 2000.- 360 с.]

Процедура partitions позволяет получить все разбиения заданного множества на не пустые подмножества. Порядок записи подмножеств - элементов разбиения считается значимым.

Искомые разбиения представлены в виде двухмерного массива – одномерного массива одномерных массивов типа vector. Используются структура vector из стандартной библиотеки STL. Процедура print(S) выводит на экран очередное разбиение.

Приведенная реализация является рекурсивной. В исходном множестве поочередно выбирается подмножество. В оставшейся части множества опять поочередно выбирается подмножество и т.д. При исчерпании элментов исходного множества очередное разбиение получено и выполняется переход к формированию следующего разбиения.

Переменная b типа unsigned long используется для битового представления очередного подмножества, отсюда имеем максимальный размер исходного множества для приведенной реализации - 32. Рассматривать исходное множество большего размера не имеет смысла, т.к. число разбиений оказывается слишком велико для любого численного анализа.

#include <syst.h>

#include <vector.h>

void partitions(vector<int> & A) // A – исходное множество, затем оч. подмнож.

{ static M; // Номер очередного разбиения

int i, n = A.size();

unsigned long b, t;

vector<int> R, C;

static vector < vector<int> > S;

for (b=1; b < pow(2,n); b++)

{ t=0x0001; R=C=vector<int>();

for (i=0;i<n;i++) { if (b&t) R.push_back(A[i]);

else C.push_back(A[i]);

t <<= 1;

}

S.push_back(R);

if (C.empty()) { M++; printf("%4d -> ", M);

print(S); return;

}

partitions(C);

S.pop_back(); S.pop_back();

}

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: