问题
I want to find the best solution from all brute force combinations of a dictionary. For the context of the problem, I need to find out the minimum number of trips needed to transport all the cows given a weight limit.
The combinations are already given to me with the helper functions get_partitions
. The function returns a nested list, with each inner list represents a trip and names of cows on that trip.
Helper functions:
def partitions(set_):
if not set_:
yield []
return
for i in range(2**len(set_)//2):
parts = [set(), set()]
for item in set_:
parts[i&1].add(item)
i >>= 1
for b in partitions(parts[1]):
yield [parts[0]]+b
def get_partitions(set_):
for partition in partitions(set_):
yield [list(elt) for elt in partition]
What I tried to do was sorting all combinations by length then iterate over them with a nested loop. If the total weight exceed the limit, then I break out of the inner loop and append the next sublist to another list. The problem is that the next sublist still contain leftover lists from the partition since their total weight is below the limit.
My code:
def brute_force_cow_transport(cows, limit):
# Generate and sort all combinations by length
partitions = [item for item in get_partitions(cows)]
partitions.sort(key=len)
# Iterate over each sublist of combinations
possibles = []
for partition in partitions:
trips = []
for section in partition:
total = sum([cows.get(cow) for cow in section])
if total > limit:
break
else:
# Appending next sublists create duplicates
trips.append(section)
possibles.append(trips)
# Remove duplicates from possible solutions
best = []
for item in possibles:
if item and item not in best:
best.append(item)
return min(best)
When I run my function, it keeps returning a different result each time. I think it's because the leftover sublists I appended to the results is causing the problem but I'm not sure:
cows = {'MooMoo': 50, 'Miss Bella': 25, 'Boo': 20,
'Milkshake': 40, 'Horns': 25, 'Lotus': 40}
>>> brute_force_cow_transport(cows, limit=100)
[['Boo', 'Miss Bella', 'MooMoo']]
Correct result:
[['MooMoo', 'Horns', 'Miss Bella'], ['Milkshake', 'Lotus', 'Boo']]
If anyone can help me point out where I went wrong, that would be greatly appreciated.
Edit: Added helper functions
回答1:
We can approach this as a depth-first-search problem.
def getCows(dict, limit):
best_solution = []
best_solution_score = 0
def dfs(current_cows, current_total):
nonlocal best_solution_score
nonlocal best_solution
if current_total > best_solution_score:
#replace best solution
best_solution = [tuple(sorted(current_cows))]
best_solution_score = current_total
elif current_total == best_solution_score:
#add to best solution
best_solution.append(tuple(sorted(current_cows)))
for cow, weight in dict.items():
if cow not in current_cows and current_total + weight <= limit:
#if adding next cow under limit recurse
dfs(current_cows + [cow], current_total + weight)
dfs([], 0)
return list(set(best_solution)) #remove duplicates
cows = {'MooMoo': 50, 'Miss Bella': 25, 'Boo': 20,
'Milkshake': 40, 'Horns': 25, 'Lotus': 40}
print(getCows(cows, limit=100))
>>>[('Horns', 'Miss Bella', 'MooMoo'), ('Boo', 'Lotus', 'Milkshake')]
来源:https://stackoverflow.com/questions/49826746/how-to-find-best-solution-from-all-brute-force-combinations