看似与图论完全无关的问题,也可以用图论解决。
在一个容量为
v
1
v_1
v1的瓶中装满一瓶酒,还有两个容量分别为
v
2
v_2
v2与
v
3
v_3
v3的空瓶,问将容量为
v
1
v_1
v1的瓶中的酒平分最少需要几次,以及如何倒水。当
v
1
v_1
v1为奇数时,平分向下取整。(
b
1
>
b
2
>
b
1
2
>
b
3
b_1>b_2>\frac{b_1}{2}>b_3
b1>b2>2b1>b3)
class BottleState(object):
def __init__(self, bottle1, bottle2, bottle3, volumes):
self.__bottles_state = [bottle1, bottle2, bottle3]
self.__volumes = volumes
def pour(self, from_bottle, to_bottle):
if self.__bottles_state[from_bottle] < self.__volumes[to_bottle] - self.__bottles_state[to_bottle]:
pour_volume = self.__bottles_state[from_bottle]
else:
pour_volume = self.__volumes[to_bottle] - self.__bottles_state[to_bottle]
new_bottle_state = self.__bottles_state.copy()
new_bottle_state[from_bottle] -= pour_volume
new_bottle_state[to_bottle] += pour_volume
return BottleState(new_bottle_state[0], new_bottle_state[1], new_bottle_state[2], self.__volumes)
def get_state(self):
return tuple(self.__bottles_state)
def __eq__(self, other):
return self.get_state() == other.get_state()
class BreadFirstPaths(object):
def __init__(self, start, end):
self.__start = start
self.__end = end
self.__marked = [start.get_state()]
self.__former_state = [start]
self.bfs()
def bfs(self):
fringe = [self.__start]
while fringe:
current_state = fringe.pop(0)
if current_state == self.__end:
break
for from_bottle, to_bottle in zip([0, 0, 1, 1, 2, 2], [1, 2, 0, 2, 0, 1]):
new_bottle_state = current_state.pour(from_bottle, to_bottle)
if new_bottle_state.get_state() not in self.__marked:
self.__marked.append(new_bottle_state.get_state())
fringe.append(new_bottle_state)
self.__former_state.append(self.__marked.index(current_state.get_state()))
def get_min(self):
count = 0
try:
index = self.__marked.index(self.__end.get_state())
except ValueError:
return False
while index != 0:
count += 1
index = self.__former_state[index]
return count
def get_path(self):
path = []
try:
index = self.__marked.index(self.__end.get_state())
except ValueError:
return False
while index != 0:
path.insert(0, self.__marked[index])
index = self.__former_state[index]
path.insert(0, self.__start.get_state())
return path
v1, v2, v3 = 10, 7, 3
volume = [v1, v2, v3]
end = v1 // 2
start_bottle_state = BottleState(v1, 0, 0, volume)
end_bottle_state = BottleState(end, end, v1 - 2 * end, volume)
bfp = BreadFirstPaths(start_bottle_state, end_bottle_state)
path = bfp.get_min()
if path is not False:
print(path)
print(bfp.get_path())
else:
print('路径不存在')
当然,此题还可以考虑使用裴蜀定理,将会大大降低时间复杂度与空间复杂度。在此不作讲述,有兴趣的朋友可以去力扣看一看。