Вот некоторая идея.
Если я не ошибаюсь, число массивов равно 2
N-1
, и массивы отображаются в битовые комбинации, кодирующие целые числа, образующие 0
до 2
N-1
-1
следующим образом:
Я покажу пример для N = 4
Первый массив - это все единицы.Представьте, что каждый бит в битовой комбинации соответствует границе между двумя ячейками массива
1 1 1 1 <- array elements
| | | <- sections
0 0 0 <- bit pattern
Каждый 1 в битовой комбинации означает объединение двух соседних ячеек
1 (1+1) 1 <- array elements (1 2 1)
| | | <- sections
0 1 0 <- bit pattern
1 (1+1+1) <- array elements (1 3)
| | | <- sections
0 1 1 <- bit pattern
(1+1) (1+1)<- array elements (2 2)
| | | <- sections
1 0 1 <- bit pattern
(1+1+1+1) <- array elements (4)
| | | <- sections
1 1 1 <- bit pattern
Перечислить все массивы, которые вы можетегенерировать целые числа от 0
до 2
N-1
-1
и для каждого полученного вами битового набора генерировать соответствующий массив.Может быть полезно преобразовать целое число в строку нулей и единиц длины N-1
.Вы декодируете шаблон следующим образом:
Первая ячейка изначально содержит 1
.Пройдя по шаблону слева направо, для каждого бита, если он 1
, добавить 1
к текущей ячейке, если он 0
, создать новую ячейку, содержащую 1
.
Шаблон 1 1 0 0 1 0 1
for N = 8
будет декодирован в массив
(3 1 2 2)
Вот некоторый код C ++ без проверки аргументов и обработки шаблона справа налево.Он просто меняет порядок создаваемых массивов и его проще кодировать.
std::vector<std::vector<int> > generateArrays(unsigned int N)
{
//validate the argument before processing
// N > 0 and N <= numeric_limits<unsigned int>::digits
unsigned int numOfArrays = (1U << (N-1));
std::vector<std::vector<int> > result(numOfArrays);
for(unsigned int i = 0; i < numOfArrays; ++i)
{
result[i].push_back(1);
unsigned int mask = 1U;
while(mask < numOfArrays)
{
if((i & mask) != 0)
{
result[i].back()++;
}
else
{
result[i].push_back(1);
}
mask <<= 1;
}
}
return result;
}