from collections import Counter def recursion_foo(remain:int or float, available_weights:list, combination=dict(), combinations_to_print=list()): """Возвращает количество уникальных комбинаций заданного набора весов грузиков для заданного веса Первым возвращает уникальное количество комбинаций, позволяющий с помощью грузиков собрать нужный вес, а вторым - список комбинаций в виде словарей, где ключ - вес грузика, а значение - требуемое количество грузиков с таким весом. Логика: Для решения потребуется лишь сформировать "список" всех возможных комбинаций всех весов available_weights, а затем выбрать те, что в итоге дают заданный вес remain. Однако алгоритм будет неэффективен, поскольку сгенерированных комбинаций будет огромное количество даже при небольшом количестве весов. Таким образом, требуется ограничитель количества таких комбинаций, которым в моем решении выступила Область Допустимых Значений. При рекурсивном вызове функции на вход подается скорректированный список весов для подстановки и остаток, путем деления последнего на каждый вес в списке формируется максимальное количество грузиков каждого веса, которое можно использовать в этой комбинации, где ОДЗ = range(0, максимальное_количество+1). P.S. Кроме того, такой подход с легкостью позволяет внедрить заданные пользователем ограничения по количеству заданного набора весов грузиков, где максимальным количеством при определении ОДЗ будет выступать наименьшее из чисел, полученных при делении остатка на вес грузика и передачи ограничения на максимальное количество грузиков самим пользователем. """ bound_dict = dict() for weight in available_weights: bound_dict[weight] = int(remain//weight) # ОДЗ for w,value in bound_dict.items(): for possible_weight in range(value+1): combination[w] = possible_weight if len(available_weights) == 1: final_sum = w*possible_weight if final_sum != remain: continue else: tmp_to_add = [] for good_weight, good_value in combination.items(): tmp_to_add += [good_weight]*good_value if tmp_to_add not in combinations_to_print: combinations_to_print.append(tmp_to_add) global result result = len(combinations_to_print) global comb_dict comb_dict = [dict(Counter(comb_list)) for comb_list in combinations_to_print] else: # копирование и удаление использованного веса new_available_weights = list(tuple(available_weights)) new_available_weights.remove(new_available_weights[new_available_weights.index(w)]) # расчет нового остатка new_remain = (remain-w*possible_weight) # запуск нового круга рекурсии recursion_foo(new_remain, new_available_weights, combination) return result,comb_dict result,comb_dict = recursion_foo(remain=5, available_weights=[3,2,1,0.5]) print('Уникальное количество комбинаций, позволяющий с помощью грузиков собрать нужный вес: ', result) print('===============================================================================================') print('Комбинации в виде словарей, где ключ - вес грузика, а значение - требуемое количество грузиков с таким весом: ', comb_dict)
Run
Reset
Share
Import
Link
Embed
Language▼
English
中文
Python Fiddle
Python Cloud IDE
Follow @python_fiddle
Browser Version Not Supported
Due to Python Fiddle's reliance on advanced JavaScript techniques, older browsers might have problems running it correctly. Please download the latest version of your favourite browser.
Chrome 10+
Firefox 4+
Safari 5+
IE 10+
Let me try anyway!
url:
Go
Python Snippet
Stackoverflow Question