Генерация подмножеств конечного множества на С++

Алгоритмы: от сортировки пузырьком до численных методов

Модераторы: C_O_D_E, DeeJayC

Ответить
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

25 май 2004, 22:59

Мысль в общем правильная, в верном направлении :)

Рассмотрим множество из N различных элементов M = {a(1),..,a(N)}. Любое его подмножество может быть представлено в виде сигнатуры (s(1),..,s(N)), где s(i) = 0|1 имеет смысл 'элемент a(i) входит в подмножество S'. Поскольку элементы M различны, любой комбинации из 0 и 1 длиной N однозначно соответствует некоторое подмножество исходного множества M, и наоборот, любому подмножеству M соответствует некоторая комбинация нулей и единиц. А теперь вспомним, что целые числа в двоичной системе представляются именно как последовательность нулей и единиц. Рассмотрим, например, множество неотрицательных целых чисел от 0 до 2^N-1 в двоичном представлении:

0 0000..0000 (N нулей)
1 0000..0001 (N-1 нуль, последняя 1)
2 0000..0010 (N-1 нуль, предпоследняя 1)
3 0000..0011 (N-2 нуля, 2 предпоследние 1)
и т.д.
2^N-1 1111..1111 (N единиц)

Очевидно, мы таким образом установили вз.-однозначное соответствие между множеством целых чисел от 0 до 2^N-1 и множеством всевозможных подмножеств M.

Теперь вопрос, как все это запрограммировать. Думаю, что для учебных целей достаточно будет смоделировать множество с небольшим числом элементов, например, N<=32. Тогда все элементарно: объявляешь переменную типа unsigned long (32 бита, как раз) и в последовательно ее инкрементируешь от 0 до 2^N-1. А в цикле просто выводишь ее двоичное представление и интерпретируешь как сигнатуру подмножества.
Ответить