Участник:Irdkwmnsb — различия между версиями
Irdkwmnsb (обсуждение | вклад) (submit) |
Irdkwmnsb (обсуждение | вклад) (→Специализация алгоритма для генерации следующего разбиения на подмножества) |
||
(не показана 1 промежуточная версия этого же участника) | |||
Строка 12: | Строка 12: | ||
'''Рассмотрим алгоритм нахождения лексикографически следующего разбиения на подмножества:''' | '''Рассмотрим алгоритм нахождения лексикографически следующего разбиения на подмножества:''' | ||
− | *Будем хранить подмножества в списке списков, например, разбиение <tex> \{1, 2, 3\}~ \{4, 5\}</tex> будет выглядеть так: | + | *Будем хранить подмножества в списке списков, например, разбиение <tex> \{1, 2, 3\} ~ \{4, 5\}</tex> будет выглядеть так: |
{| class="wikitable" border = 1 | {| class="wikitable" border = 1 | ||
Строка 20: | Строка 20: | ||
|} | |} | ||
− | * Будем поддерживать массив | + | * Будем поддерживать массив удалённых элементов {{---}} элементы, которые затем нужно будет вернуть в разбиение. |
* Двигаясь снизу вверх будем рассматривать подмножества. | * Двигаясь снизу вверх будем рассматривать подмножества. | ||
− | ** Если мы можем дописать в текущее подмножество минимальный элемент из удалённых, то мы нашли следующее разбиение и | + | ** Если мы можем дописать в текущее подмножество минимальный элемент из удалённых, то мы нашли следующее разбиение и нужно завершить цикл. |
− | ** Если дописать не можем, значит, либо нужно укоротить и заменить какой то элемент в текущем подмножестве, либо перейти к следующему подмножеству. Будем идти справа налево и | + | ** Если дописать не можем, значит, либо нужно укоротить и заменить какой-то элемент в текущем подмножестве, либо перейти к следующему подмножеству. Будем идти справа налево и рассматривать элементы: |
− | *** Если мы можем заменить текущий элемент минимальным удалённым {{---}} мы нашли следующее разбиение, завершаем оба | + | *** Если мы можем заменить текущий элемент минимальным удалённым {{---}} мы нашли следующее разбиение, завершаем оба цикла и выполняем алгоритм дальше. Стоит отметить, что нельзя перезаписывать последний элемент в подмножестве, иначе мы не сможем дописать минимальный хвост после этого подмножества {{---}} в удалённых будет элемент меньше текущего и мы не сможем выписать удаленные элементы так, чтобы получилось корректное разбиение. |
− | *** Если заменить | + | *** Если заменить текущий элемент каким-то из удалённых нельзя, то следует удалить и этот. |
* Допишем лексикографически минимальный хвост подмножеств из оставшихся удалённых элементов. | * Допишем лексикографически минимальный хвост подмножеств из оставшихся удалённых элементов. | ||
Строка 79: | Строка 79: | ||
| ||^|| ||Удалили элемент 5. | | ||^|| ||Удалили элемент 5. | ||
|- | |- | ||
− | | || || || | + | | || || ||Удалённые элементы |
|} | |} | ||
Строка 92: | Строка 92: | ||
|^|| || ||Удалили элемент 4. Так как он является последним в подмножестве, то мы не можем заменить его на другой. | |^|| || ||Удалили элемент 4. Так как он является последним в подмножестве, то мы не можем заменить его на другой. | ||
|- | |- | ||
− | |5|| || || | + | |5|| || ||Удалённые элементы |
|} | |} | ||
Строка 103: | Строка 103: | ||
| || || ||^||Дополнили первое подмножество элементом 4 | | || || ||^||Дополнили первое подмножество элементом 4 | ||
|- | |- | ||
− | |5|| || || || | + | |5|| || || ||Удалённые элементы |
|} | |} | ||
Строка 114: | Строка 114: | ||
|style="background:#FFCC00"|5|| || || ||Дописали лексикографически минимальный хвост | |style="background:#FFCC00"|5|| || || ||Дописали лексикографически минимальный хвост | ||
|- | |- | ||
− | | || || || || | + | | || || || ||Удалённые элементы |
|} | |} |
Текущая версия на 13:14, 7 января 2021
Специализация алгоритма для генерации следующего разбиения на подмножества
Рассмотрим множество первых n натуральных чисел:
Упорядочим все разбиения на множества
лексикографически. Для этого, во-первых, в каждом разбиении упорядочим множества лексикографически. Будем говорить, что подмножество лексикографически меньше подмножества , если верно одно из следующих условий:- существует такое, что , , для всех если и только если , и существует такое что ;
- и для всех и \ .
Разбиения упорядочены лексикографически следующим образом. Разбиение
лексикографически меньше разбиения если существует такое , что .
Рассмотрим алгоритм нахождения лексикографически следующего разбиения на подмножества:
- Будем хранить подмножества в списке списков, например, разбиение будет выглядеть так:
1 | 2 | 3 |
4 | 5 |
- Будем поддерживать массив удалённых элементов — элементы, которые затем нужно будет вернуть в разбиение.
- Двигаясь снизу вверх будем рассматривать подмножества.
- Если мы можем дописать в текущее подмножество минимальный элемент из удалённых, то мы нашли следующее разбиение и нужно завершить цикл.
- Если дописать не можем, значит, либо нужно укоротить и заменить какой-то элемент в текущем подмножестве, либо перейти к следующему подмножеству. Будем идти справа налево и рассматривать элементы:
- Если мы можем заменить текущий элемент минимальным удалённым — мы нашли следующее разбиение, завершаем оба цикла и выполняем алгоритм дальше. Стоит отметить, что нельзя перезаписывать последний элемент в подмножестве, иначе мы не сможем дописать минимальный хвост после этого подмножества — в удалённых будет элемент меньше текущего и мы не сможем выписать удаленные элементы так, чтобы получилось корректное разбиение.
- Если заменить текущий элемент каким-то из удалённых нельзя, то следует удалить и этот.
- Допишем лексикографически минимальный хвост подмножеств из оставшихся удалённых элементов.
list<list<int>> nextSetPartition(list<list<int>> a): used = list<int> // a — список, содержащий подмножества // used — список, в котором мы храним удаленные элементы fl = false for i = a.size - 1 downto 0 if (used.size != 0) and (max(used) > a[i][-1]) // в удалённых есть хотя бы один элемент, который мы можем добавить в конец. m = минимум из used строго больше a[i][-1] a[i].add(m) //добавляем used.remove(m) break for j = a[i].size - 1 downto 0 if (used.size != 0) and (j != 0) and (max(used) > a[i][j]) //если можем заменить элемент, другим элементом из списка used и он не последний m = минимум из used строго больше a[i][-1] a[i][j] = m //заменяем used.remove(m) fl = true break else used.add(a[i][-1]) a[i].pop() if a[i].size == 0 a.pop() if fl break //далее выведем все удалённые, которые не выбрали sort(used) for i = 0 to used.size - 1 a.add(list<int>(used[i])) //добавляем лексикографически минимальных хвост return a
Пример работы
Рассмотрим следующее разбиение:
1 | 2 | 3 |
4 | 5 |
1 Шаг:
1 | 2 | 3 | |
4 | 5 | ||
^ | Удалили элемент 5. | ||
Удалённые элементы |
2 Шаг:
1 | 2 | 3 | |
4 | |||
^ | Удалили элемент 4. Так как он является последним в подмножестве, то мы не можем заменить его на другой. | ||
5 | Удалённые элементы |
3 Шаг:
1 | 2 | 3 | 4 | |
^ | Дополнили первое подмножество элементом 4 | |||
5 | Удалённые элементы |
4 Шаг:
1 | 2 | 3 | 4 | |
5 | Дописали лексикографически минимальный хвост | |||
Удалённые элементы |