std::next_permutation (и std::prev_permutation) переставляет все значения в диапазоне [first, last), всего n! перестановки (при условии, что все элементы уникальны).
можно ли написать такую функцию:
template<class Iter>
bool next_permutation(Iter first, Iter last, Iter choice_last);
Это переставляет элементы в диапазоне [first, last), но выбирает только элементы в диапазоне [first, choice_last). т.е. у нас есть, может быть, 20 элементов, и мы хотим перебрать все перестановки 10 вариантов из них, 20 P 10 вариантов против 20 P 20.
- Iter — это итератор с произвольным доступом для моих целей, но если его можно реализовать как двунаправленный итератор, то отлично!
- Чем меньше нужно внешней памяти, тем лучше, но для моих целей это не имеет значения.
- Выбранные элементы на каждой итерации вводятся в первые элементы последовательности.
Возможна ли реализация такой функции? Кто-нибудь знает какие-либо существующие реализации?
Вот, по сути, что я делаю, чтобы взломать это. Предложения о том, как улучшить это, также приветствуются.
- Начните с вектора
VизNэлементов, из которых я хочу посетить каждую перестановкуRэлементов, выбранных из него (R <= N). - Создайте вектор
IдлиныRсо значениями{ 0, 1, 2, ... R - 1 }, который будет служить индексом для элементовV. - На каждой итерации построить вектор
CдлиныRсо значениями{ V[I[0]], V[I[1]], ... V[I[R - 1]] } - Сделайте что-нибудь со значениями в
C. - Примените функцию для перестановки элементов
Iи повторите итерацию, если это возможно.
Эта функция выглядит так:
bool NextPermutationIndices(std::vector<int> &I, int N)
{
const int R = I.size();
for (int i = R - 1; ; --i) {
if (I[i] < N - R + i) {
++I[i];
return true;
}
if (i == 0)
return false;
if (I[i] > I[i-1] + 1) {
++I[i-1];
for (int j = i; j < R; ++j)
I[j] = I[j-1] + 1;
return true;
}
}
}
Эта функция очень сложна из-за всех возможных ошибок, а также все, что ее использует, сложнее, чем это, возможно, необходимо.
ИЗМЕНИТЬ:
Оказывается, это было значительно проще, чем я даже мог себе представить. Из здесь я смог найти точные реализации многих точных нужные мне алгоритмы (комбинации, перестановки и т.д.).
template<class BidirectionalIterator>
bool next_partial_permutation(BidirectionalIterator first,
BidirectionalIterator middle,
BidirectionalIterator last)
{
std::reverse(middle, last);
return std::next_permutation(first, last);
}
Плюс там есть алгоритм комбинирования, который работает аналогичным образом. Однако реализация этого гораздо сложнее.
bool next_permutation(Iter first, Iter last, int result_count), чтобы сделать намерение более ясным. - person David Schmitt   schedule 26.10.2008