Думать об этом как о проблеме дерева - это красная сельдь, это действительно ориентированный граф. Но забудьте об этом все.
Думайте о стакане где-нибудь ниже верхнего. Над ним будет один или два стакана, которые могут перетекать в него. При соответствующем выборе системы координат (не волнуйтесь, смотрите конец) мы можем написать функцию, чтобы получить «родительские» очки для любого данного стекла.
Теперь мы можем придумать алгоритм, позволяющий получать количество жидкости, наливаемой в стакан, независимо от переполнения из этого стакана. Ответ, однако, заключается в том, что в каждого родителя наливается много жидкости, минус количество, хранящееся в каждом родительском стакане, деленное на 2. Просто сложите сумму для всех родителей. Записываем это как фрагмент python тела функции amount_poured_into ():
# p is coords of the current glass
amount_in = 0
for pp in parents(p):
amount_in += max((amount_poured_into(total, pp) - 1.0)/2, 0)
Max () должен гарантировать, что мы не получим отрицательное количество переполнения.
Мы почти закончили! Мы выбираем систему координат с 'y' вниз по странице, очки первой строки равны 0, вторая строка равна 1 и т. Д. Координаты 'x' имеют ноль под стеклом верхнего ряда, а вторая строка имеет координаты x -1 и +1, третий ряд -2, 0, +2 и т. Д. Важным моментом является то, что левое или самое правое стекло на уровне у будет иметь абс (х) = у.
Оборачивая все это в python (2.x), мы имеем:
def parents(p):
"""Get parents of glass at p"""
(x, y) = p
py = y - 1 # parent y
ppx = x + 1 # right parent x
pmx = x - 1 # left parent x
if abs(ppx) > py:
return ((pmx,py),)
if abs(pmx) > py:
return ((ppx,py),)
return ((pmx,py), (ppx,py))
def amount_poured_into(total, p):
"""Amount of fluid poured into glass 'p'"""
(x, y) = p
if y == 0: # ie, is this the top glass?
return total
amount_in = 0
for pp in parents(p):
amount_in += max((amount_poured_into(total, pp) - 1.0)/2, 0)
return amount_in
def amount_in(total, p):
"""Amount of fluid left in glass p"""
return min(amount_poured_into(total, p), 1)
Таким образом, чтобы получить сумму на самом деле в стакане при p, используйте amount_in (total, p).
Это не ясно из ОП, но немного о «вы не можете добавить параметры» может означать, что на исходный вопрос необходимо ответить в терминах показанных чисел стекла . Это решается путем записи функции сопоставления номеров витрин во внутреннюю систему координат, использованную выше. Это неудобно, но можно использовать итеративное или математическое решение. Легко понять итеративную функцию:
def p_from_n(n):
"""Get internal coords from glass 'number'"""
for (y, width) in enumerate(xrange(1, n+1)):
if n > width:
n -= width
else:
x = -y + 2*(n-1)
return (x, y)
Теперь просто переписайте приведенную выше функцию amount_in (), чтобы принять номер стекла:
def amount_in(total, n):
"""Amount of fluid left in glass number n"""
p = p_from_n(n)
return min(amount_poured_into(total, p), 1)