Я предполагаю, что все интервальные записи положительны. Один из подходов динамического программирования c заключается в представлении состояния в виде (n, t)
, где n
- индекс текущего интервала, а t
- целевая сумма. Например, начальное состояние в вашем примере: n=0
и t=4
.
Позвольте f(n, t)
обозначить количество способов, которыми мы можем выбрать один элемент от интервала n
до последнего сумма выбранных элементов составляет t
. Затем в псевдокоде
f(n, t) = sum(f(n+1), t - row[n][j]) for j <= len(row[n]))
Вот одна из возможных реализаций с использованием Python; naive
функция` включена для проверки правильности (предполагается, что все интервалы имеют одинаковую длину).
def naive(xs, target):
from itertools import product
res = 0
for tup in product(*xs):
res += sum(tup) == target
return res
def one_per_row_sums(xs, target):
n = len(xs)
if n == 0:
return 0
m = len(xs[0])
assert all(len(x) == m for x in xs)
def f(n, k):
if k < 0:
return 0
if n == 0:
return sum(1 if x == k else 0 for x in xs[n])
else:
return sum(f(n-1, k-j) for j in xs[n])
return f(n-1, target)
xs = [[0, 1, 2], [0, 1, 2]]
assert naive(xs, 4) == one_per_row_sums(xs, 4)
# larger test
import numpy as np
n = 6
m = 6
xs = np.sort(np.random.randint(0, 10, (n, m)), axis=1)
assert one_per_row_sums(xs, 20) == naive(xs, 20)