Мы можем доказать это, сформировав логическое повторение:
(A) Если максимальная высота стека при заданных m и k меньше n, мы не можем создать никакой стек.
( Б) Если разрешен только один тайл, мы можем выбрать m разных размеров для этого тайла.
(C) Если разрешен только один размер, если k больше или равно n, мы можем построить одна стопка из n плиток размера 1; в противном случае - ноль стеков.
(D) Для каждого возможного количества x плиток размера m, сложенных в стопку, у нас есть один способ, который умножается на количество способов укладки (n - x) плиток, используя размеры не более (m - 1), поскольку мы использовали m.
Чтобы преобразовать повторение в программирование с восходящей динамикой c, мы инициализируем матрицу, используя базовые случаи повторения, и заполняем последующие записей, использующих его логическую ветвь общего регистра.
Вот демонстрация повторения в JavaScript (извините, я не разбираюсь в C ++, но первая функция, f
, которая вычисляет только количество, должна быть очень легко преобразовать):
// Returns the count
function f(n, m, k){
if (n > m * k)
return 0;
if (n == 1)
return m;
if (m == 1)
return n <= k ? 1 : 0;
let result = 0;
for (let x=0; x<=k; x++)
result += f(n - x, m - 1, k);
return result;
}
// Returns the sequences
function g(n, m, k){
if (n > m * k)
return [];
if (n == 1)
return new Array(m).fill(0).map((_, i) => [i + 1]);
if (m == 1)
return n <= k ? [new Array(n).fill(1)] : [];
let result = [];
for (let x=0; x<=k; x++){
const pfx = new Array(x).fill(m);
const prev = g(n - x, m - 1, k);
for (let s of prev)
result.push(pfx.concat(s));
}
return result;
}
var inputs = [
[3, 3, 1],
[3, 3, 2],
[1, 2, 2]
];
for (let args of inputs){
console.log('' + args);
console.log(f(...args));
console.log(JSON.stringify(g(...args)));
console.log('');
}