Получение следующего объекта — различия между версиями
Shersh (обсуждение | вклад) |
Korektur (обсуждение | вклад) |
||
| Строка 63: | Строка 63: | ||
== Специализация алгоритма для генерации следующего разбиения на подмножества == | == Специализация алгоритма для генерации следующего разбиения на подмножества == | ||
| + | {{Определение | ||
| + | |id=def1. | ||
| + | |definition='''Разбиением на множества''' называется представление множества, как объединения одного или более, попарно | ||
| + | непересекающихся подмножеств множеств. | ||
| + | }} | ||
| + | Например для n = 5 существуют следующие разбиения: | ||
| + | |||
| + | '''{1, 2, 3, 4, 5}''' | ||
| + | |||
| + | '''{1, 2, 3} {4, 5}''' | ||
| + | |||
| + | '''{1, 3, 5} {2, 4}''' | ||
| + | |||
| + | '''{1} {2} {3} {4} {5}''' | ||
| + | |||
| + | и т. д., всего таких разбиений для n = 5 существует 52. | ||
| + | |||
| + | '''Примечание:''' | ||
| + | {1, 2, 3} {4, 5} и {4, 5} {1, 2, 3} - одно и то же разбиение на подмножества. | ||
| + | |||
| + | Упорядочим все разбиения на множества Nn лексикографически. Для этого во-первых в каждом разбиении упорядочим множества лексикографически. Будем говорить, что подмножество <tex> A \subset N_n </tex> лексикографически меньше подмножества <tex> B \subset N_n </tex> , если верно одно из следующих условий: | ||
| + | |||
| + | *существует i такое, что <tex>i \in A</tex> , <tex>i \notin A</tex>, для всех j < i: <tex>j \in A</tex> если и только если <tex>j \in B</tex> , и существует k > i такое что <tex>k \in B</tex>; | ||
| + | * <tex> A \subset B </tex> и i < j для всех <tex>i \in A</tex> и <tex>j \in B</tex> \ <tex> A </tex>. | ||
| + | |||
| + | Разбиения упорядочены лексикографически следующим образом. Разбиение <tex>N_n = A_1 \cup A_2 \cup . . . \cup A_k</tex> лексикографически меньше разбиения <tex>N_n = B_1 \cup B_2 \cup . . . \cup B_l</tex> если существует такое <tex>i</tex>, что <tex>A_1 = B_1, A_2 = B_2, . . . ,A_{i - 1} = B_{i - 1}, A_i < B_i</tex>. | ||
| + | |||
| + | |||
| + | '''Рассмотрим алгоритм нахождения лексикографически следующего разбиения на подмножества:''' | ||
| + | *Будем хранить подмножества с помощью двумерного массива, например, разбиение {1, 2, 3} {4, 5} будет выглядеть так: | ||
| + | |||
| + | {| class="wikitable" border = 1 | ||
| + | |1||2||3 | ||
| + | |- | ||
| + | |4||5|| | ||
| + | |} | ||
| + | |||
* Двигаясь снизу вверх и справа налево, будем удалять элементы, записывая их в отдельный массив. Будем повторять эту операцию, пока не выполнится одно из условий ниже: | * Двигаясь снизу вверх и справа налево, будем удалять элементы, записывая их в отдельный массив. Будем повторять эту операцию, пока не выполнится одно из условий ниже: | ||
** Каждый раз, рассматривая новый элемент, будем пытаться заменить его уже удаленным элементом из нашего массива, так, чтобы не нарушалась возрастающая последовательность элементов в этом подмножестве. Из всех подходящих элементов выбираем минимальный. '''Важное замечание''': мы не можем заменить 1ый элемент подмножества, мы можем только удалить его. | ** Каждый раз, рассматривая новый элемент, будем пытаться заменить его уже удаленным элементом из нашего массива, так, чтобы не нарушалась возрастающая последовательность элементов в этом подмножестве. Из всех подходящих элементов выбираем минимальный. '''Важное замечание''': мы не можем заменить 1ый элемент подмножества, мы можем только удалить его. | ||
| Строка 71: | Строка 108: | ||
// a - матрица содержащая подмножества | // a - матрица содержащая подмножества | ||
// used - массив в котором мы храним, удаленные элементы | // used - массив в котором мы храним, удаленные элементы | ||
| − | for i = n | + | for i = n downto 0 |
| − | if | + | if /*можем добавить в конец подмножества элемент из used*/ |
// добавляем | // добавляем | ||
break; | break; | ||
| − | + | for j = a[i].size() - 1 downto 0 | |
| − | for j = | + | if /* можем заменить элемент, другим элементом из массива used*/ |
| − | if | ||
//заменяем | //заменяем | ||
break; | break; | ||
| − | + | used.add(a[i][j]); //удаляем элемент и добавляем его в массив | |
| − | used.add(a[i][j]); //удаляем элемент и добавляем его в массив | + | printsets(); //далее выведем все получившиеся подмножества |
| − | printsets(); | + | </code> |
| − | |||
| − | |||
| − | |||
| − | </code> | ||
=== Пример работы === | === Пример работы === | ||
'''Рассмотрим следующее разбиение:''' | '''Рассмотрим следующее разбиение:''' | ||
| − | {1 | + | |
| − | + | {| class="wikitable" border = 1 | |
| + | |1||2||3 | ||
| + | |- | ||
| + | |4||5|| | ||
| + | |} | ||
'''1 Шаг:''' | '''1 Шаг:''' | ||
| − | |||
| − | |||
| − | |||
| − | Удалили элемент 5. | + | {| class="wikitable" border = 1 |
| + | |1||2||3|| | ||
| + | |- | ||
| + | |4||style="background:#FFCC00"|5|||| | ||
| + | |- | ||
| + | | ||^|| ||Удалили элемент 5. | ||
| + | |- | ||
| + | | || || ||used | ||
| + | |} | ||
| + | |||
'''2 Шаг:''' | '''2 Шаг:''' | ||
| − | |||
| − | |||
| − | Удалили элемент 4. Так как он является первым в подмножестве, то мы не можем заменить его на другой. | + | {| class="wikitable" border = 1 |
| + | |1||2||3|| | ||
| + | |- | ||
| + | |style="background:#FFCC00"|4|| |||| | ||
| + | |- | ||
| + | |^|| || ||Удалили элемент 4. Так как он является первым в подмножестве, то мы не можем заменить его на другой. | ||
| + | |- | ||
| + | |5|| || ||used | ||
| + | |} | ||
| + | |||
'''3 Шаг:''' | '''3 Шаг:''' | ||
| − | |||
| − | |||
| − | |||
| − | Дополнили первое подмножество элементом 4 | + | {| class="wikitable" border = 1 |
| + | |1||2||3||style="background:#FFCC00"|4|| | ||
| + | |- | ||
| + | | || || ||^||Дополнили первое подмножество элементом 4 | ||
| + | |- | ||
| + | |5|| || || ||used | ||
| + | |} | ||
| + | |||
| + | '''4 Шаг:''' | ||
| + | |||
| + | {| class="wikitable" border = 1 | ||
| + | |1||2||3||4|| | ||
| + | |- | ||
| + | |style="background:#FFCC00"|5|| || || ||Дописали лексикографически минимальный хвост | ||
| + | |- | ||
| + | | || || || ||used | ||
| + | |} | ||
== Ссылки == | == Ссылки == | ||
* [[Получение объекта по номеру]] | * [[Получение объекта по номеру]] | ||
Версия 19:40, 22 декабря 2012
Содержание
Алгоритм
| Определение: |
| Получение следующего объекта — это нахождение объекта, следующего за данным в лексикографическом порядке. |
Объект называется следующим за , если и не найдется такого , что .
Отсюда понятен алгоритм:
- Находим суффикс минимальной длины, который можно изменить без изменения префикса текущего объекта
- К оставшейся части дописываем минимальный возможный элемент (чтобы было выполнено правило )
- Дописываем минимальный возможный хвост
По построению получаем, что — минимально возможный.
Специализация алгоритма для генерации следующего битового вектора
- Находим минимальный суффикс, в котором есть 0, его можно увеличить, не меняя оставшейся части
- Вместо 0 записываем 1
- Дописываем минимально возможный хвост из нулей
for i = n downto 1
if a[i] == 0
a[i] = 1
for j = i + 1 to n
a[j] = 0
break
Пример работы
| 0 | 1 | 0 | 1 | 1 | исходный битовый вектор |
| ^ | находим элемент 0 (самый правый) | ||||
| 0 | 1 | 1 | 1 | 1 | меняем его на 1 |
| 0 | 1 | 1 | 0 | 0 | меняем элементы правее на нули |
| 0 | 1 | 1 | 0 | 0 | следующий битовый вектор |
Специализация алгоритма для генерации следующей перестановки
- Двигаясь справа налево, находим элаемент, нарушающий убывающую последовательность (в обычном порядке, слева направо, см. пример)
- Меняем его с минимальным элементом, большим нашего, стоящим правее
- Перевернем правую часть
for i = n - 1 downto 1
if a[i] < a[i + 1]
// a[j] = min {a[j] > a[i], где j > i}
swap(a[i], a[j])
reverse(a[i + 1] .. a[n])
break
Пример работы
| 1 | 3 | 2 | 5 | 4 | исходная перестановка |
| ^ | находим элемент, нарушающий убывающую последовательность | ||||
| ^ | минимальный элемент больше нашего | ||||
| 1 | 3 | 4 | 5 | 2 | меняем их местами |
| 1 | 3 | 4 | 2 | 5 | разворачивам правую часть |
| 1 | 3 | 4 | 2 | 5 | следующая перестановка |
Специализация алгоритма для генерации следующего разбиения на подмножества
| Определение: |
| Разбиением на множества называется представление множества, как объединения одного или более, попарно непересекающихся подмножеств множеств. |
Например для n = 5 существуют следующие разбиения:
{1, 2, 3, 4, 5}
{1, 2, 3} {4, 5}
{1, 3, 5} {2, 4}
{1} {2} {3} {4} {5}
и т. д., всего таких разбиений для n = 5 существует 52.
Примечание: {1, 2, 3} {4, 5} и {4, 5} {1, 2, 3} - одно и то же разбиение на подмножества.
Упорядочим все разбиения на множества Nn лексикографически. Для этого во-первых в каждом разбиении упорядочим множества лексикографически. Будем говорить, что подмножество лексикографически меньше подмножества , если верно одно из следующих условий:
- существует i такое, что , , для всех j < i: если и только если , и существует k > i такое что ;
- и i < j для всех и \ .
Разбиения упорядочены лексикографически следующим образом. Разбиение лексикографически меньше разбиения если существует такое , что .
Рассмотрим алгоритм нахождения лексикографически следующего разбиения на подмножества:
- Будем хранить подмножества с помощью двумерного массива, например, разбиение {1, 2, 3} {4, 5} будет выглядеть так:
| 1 | 2 | 3 |
| 4 | 5 |
- Двигаясь снизу вверх и справа налево, будем удалять элементы, записывая их в отдельный массив. Будем повторять эту операцию, пока не выполнится одно из условий ниже:
- Каждый раз, рассматривая новый элемент, будем пытаться заменить его уже удаленным элементом из нашего массива, так, чтобы не нарушалась возрастающая последовательность элементов в этом подмножестве. Из всех подходящих элементов выбираем минимальный. Важное замечание: мы не можем заменить 1ый элемент подмножества, мы можем только удалить его.
- Каждый раз, переходя в новое подмножество, будем пытаться дополнить его элементом из уже удаленных, так, чтобы не нарушалась возрастающая последовательность элементов в этом подмножестве. Из всех подходящих элементов выбираем минимальный.
- Допишем лексикографически минимальный хвост подмножеств из оставшихся элементов.
// a - матрица содержащая подмножества
// used - массив в котором мы храним, удаленные элементы
for i = n downto 0
if /*можем добавить в конец подмножества элемент из used*/
// добавляем
break;
for j = a[i].size() - 1 downto 0
if /* можем заменить элемент, другим элементом из массива used*/
//заменяем
break;
used.add(a[i][j]); //удаляем элемент и добавляем его в массив
printsets(); //далее выведем все получившиеся подмножества
Пример работы
Рассмотрим следующее разбиение:
| 1 | 2 | 3 |
| 4 | 5 |
1 Шаг:
| 1 | 2 | 3 | |
| 4 | 5 | ||
| ^ | Удалили элемент 5. | ||
| used |
2 Шаг:
| 1 | 2 | 3 | |
| 4 | |||
| ^ | Удалили элемент 4. Так как он является первым в подмножестве, то мы не можем заменить его на другой. | ||
| 5 | used |
3 Шаг:
| 1 | 2 | 3 | 4 | |
| ^ | Дополнили первое подмножество элементом 4 | |||
| 5 | used |
4 Шаг:
| 1 | 2 | 3 | 4 | |
| 5 | Дописали лексикографически минимальный хвост | |||
| used |