Примечание: проблема та же, что и у другой распространенной проблемы: сколько существует способов бросить определенную сумму, используя кости с d1, d2, d3, ..., dn сторон.
Если есть C[n, i] способов мойки n автомобилей за i дней, есть сумма (C [nk], i + 1), k = 1..D [i + 1]) способов мойки n автомобилей за i + 1 день.С краевыми условиями: C [0, 0] = 1, C [0, _] = 0.
Это непосредственно дает этот алгоритм O (Cmax (D) | D |), который использует O (C) пробел.
def cars(C, D):
r = [1] + [0] * C
for d in D:
for i in range(C, -1, -1):
r[i] = sum(r[j] for j in range(max(0, i-d), i))
return r[C]
print(cars(5, [2, 3, 4]))
Вы можете сделать немного лучше, поскольку внутренний цикл выполняет скользящую сумму значений d, которые могут быть вычислены за O (1) раз в среднем на элемент C.
def cars(C, D):
r = [1] + [0] * C
for d in D:
S = 0
for i in range(C, -d-1, -1):
if i >= 0:
S += r[i]
if i + d <= C:
S -= r[i+d]
r[i+d] = S
return r[C]
print(cars(5, [2, 3, 4]))
Поскольку без ограничения общности max (D)
Если это помогает, этокод по существу вычисляет первые C + 1 члены полинома P [D [0]] * P [D [1]] * ... * P [D [len (D) -1]], где P [d] = х + х ^ 2 + ... + х ^ д.Коэффициент x ^ C в результате является решением вашей проблемы.