Можно использовать рекурсивный алгоритм.
Подход:
1) Используем рекурсивную функцию для построения разбиений.
Невозрастающий порядок: Каждый следующий слагаемый должен быть меньше или равен предыдущему.
2) Для обеспечения лексикографического порядка будем перебирать первые элементы от 1 до N.
Алгоритм:
Начинаем с пустого разбиения, остатка суммы равного N, и максимального возможного слагаемого, равного N.
Если остаток суммы равен 0, выводим текущее разбиение.
Иначе, для каждого возможного слагаемого от 1 до минимального из текущего остатка суммы и предыдущего слагаемого:
1) Добавляем слагаемое в текущее разбиение.
2) Рекурсивно вызываем функцию с обновленным остатком суммы и текущим слагаемым как новым предыдущим слагаемым.
3) Удаляем слагаемое из текущего разбиения (backtracking).
В итоге разбиения выводятся в процессе рекурсивных вызовов, обеспечивая требуемый порядок
Реализация на c++:
#include <iostream>
#include <vector>
using namespace std;
void partition(int remaining_sum, int last_element, vector<int>& partition_so_far) {
if (remaining_sum == 0) {
for (size_t i = 0; i < partition_so_far.size(); ++i) {
cout << partition_so_far[i];
if (i + 1 < partition_so_far.size()) cout << " ";
}
cout << endl;
return;
}
for (int first_element = 1; first_element <= min(remaining_sum, last_element); ++first_element) {
partition_so_far.push_back(first_element);
partition(remaining_sum - first_element, first_element, partition_so_far);
partition_so_far.pop_back();
}
}
int main() {
int N;
cin >> N;
vector<int> partition_so_far;
partition(N, N, partition_so_far);
return 0;
}
Результат работы
1 1 1 1
2 1 1
2 2
3 1
4