2011-01-26 2 views
2

Мне нужно создать перестановки из нескольких диапазонов чисел в массиве.Перестановки множества диапазонов чисел

using namespace std; 

int generatePermutations(vector<int> &myVector, vector<vector<int> > &swappable) { 
    int i = 0, s = 0; 
    for (s = 0; s < swappable.size(); s++) { 
     do { 
      for (i = 0; i < myVector.size(); i++) { 
       printf("%i ", myVector[i]); 
      } 
      printf("\n"); 
      swappable.pop_back(); 
      generatePermutations(myVector, swappable); 
     } while (next_permutation(myVector.begin()+swappable[s][0], 
       myVector.begin()+swappable[s][1])); 
    } 
} 

int main() { 
    vector<int> myArray; 
    myArray.resize(6); 
    myArray[0] = 0; 
    myArray[1] = 1; 
    myArray[2] = 2; 
    myArray[3] = 3; 
    myArray[4] = 4; 
    myArray[5] = 5; 

    // Swappable positions (0 - first, 1 - last) 
    vector<vector<int> > swappable; 
    swappable.resize(2); 
    swappable[0].resize(2); 
    swappable[0][0] = 1; swappable[0][1] = 3; 
    swappable[1].resize(2); 
    swappable[1][0] = 4; swappable[1][1] = 6; 
    generatePermutations(myArray, swappable); 

    return 0; 
} 

В приведенном выше примере должен создавать что-то вроде этого:

0 1 2 3 4 5 
0 2 1 3 4 5 
0 1 2 3 5 4 
0 2 1 3 5 4 

Но он генерирует это:

0 1 2 3 4 5 
0 1 2 3 4 5 
+0

Что такое 'swappable' для? Почему в вашем коде нет комментариев? –

+0

Комментарий добавлен. swappable предназначен для хранения первой и последней позиций, между которыми мне нужно генерировать перестановки. –

+0

Хорошо. Вы пробовали переходить через ваш код в отладчике, чтобы увидеть * почему * он всегда дает тот же результат? –

ответ

2

Я принимаю его замена представляет собой набор диапазонов, которые могут быть заменены? Таким образом, [[1, 3], [4, 6]] означает что-либо в [1, 3) (индексы 1 и 2) можно поменять местами в этом диапазоне и аналогично для [4, 6]? Верно ли, что диапазоны никогда не будут перекрываться?

How does this look:

typedef vector<vector<int> >::const_iterator SwappableIter; 
void generatePermutations(vector<int> &data, 
          SwappableIter begin, SwappableIter end) 
{ 
    if (begin == end) { 
    print(data); 
    } 
    else { 
    vector<int>::iterator start = data.begin() + (*begin)[0], 
     stop = data.begin() + (*begin)[1]; 
    sort(start, stop); 
    do { 
     generatePermutations(data, begin + 1, end); 
    } while (next_permutation(start, stop)); 
    } 
} 
+0

Да, диапазоны никогда не будут перекрываться. –

+1

Если 'swappable' должен быть вектором диапазонов, используйте' std :: pair' или пользовательскую 'struct', а не вложенный вектор. –

+0

Да, пара была бы лучше; Я сохранил тип вопроса для моего примера. –

0

Вот немного модифицированная версия вашего алгоритма генерации (который не работает).

int generatePermutations(vector<int> &myVector, vector<vector<int> >& swappable) { 
    do 
    { 
    do 
    { 
     print(myVector); 
     // generate permutations of the second segment 
    } while(next_permutation(myVector.begin() + swappable[1][0], myVector.begin() + swappable[1][1])); 

    // re-sort the second segment 
    sort(myVector.begin() + swappable[1][0], myVector.begin() + swappable[1][1]); 

    // calculate permutation of first segment 
    } while(next_permutation(myVector.begin() + swappable[0][0], myVector.begin() + swappable[0][1])); 
} 

EDIT: исправлен для генерации комбинаций, но работает только для двух диапазонов, решение Фреда выше более масштабируемое ..

+0

Это не очень хорошо масштабируется; например когда swappable.size() == 10. –

+0

@Fred, true .... – Nim

+0

Это также [не работает] (http://ideone.com/qTuew). –

0

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

Просто удалите строки

swappable.pop_back(); 
generatePermutations(myVector, swappable); 

и код должен приступить к работе.

+0

Код в вопросе, после удаления двух строк, которые вы упоминаете, не работает. –

+0

@Fred Nurk: Позаботьтесь о том, как он не работает? Или вы имеете в виду отсутствующие утверждения '# include'? При выполнении кода с добавленным обязательным добавлением '# include и строк, о которых я упоминал, я получил результат, похожий на то, что было указано в списке @Radek. –

+0

См. Http://ideone.com/4GHv0. Обратите внимание на UB из-за последнего предупреждения, как четыре линии вывода имеют одну строку, дублируемую, и как одна строка отсутствует на ожидаемом выходе. (И, кстати, это был не мой нисходящий голос, я не спускаюсь вниз.) –

Смежные вопросы