题目
给定两个水壶,一个可装4加仑水,一个能装3加仑水。水壶上没有任何度量标记。有一水泵可用来往壶中装水。
问:怎样在能装4加仑的水壶里恰好只装2加仑水?
即:初始4加仑大水壶状态(0,0);目标4加仑大水壶状态(2,?)【问号表示任意状态】
X = 大壶
Y = 小壶
根据题目可以确定每一组的操作
1(X,Y|X<4)→(4,Y) 4加仑水壶不满时,将其装满;
2(X,Y|Y<3)→(X,3) 3加仑水壶不满时,将其装满;
3(X,Y|X>0)→(0,Y) 把4加仑水壶中的水全部倒出;
4(X,Y|Y>0)→(X,0) 把3加仑水壶中的水全部倒出;
5(X,Y|X+Y≥4∧Y>0)→(4,Y-(4-X)) 把3加仑水壶中的水往4加仑水壶里倒,直至4加仑水壶装满为止 ;
6(X,Y|X+Y≥3∧X>0)→(X-(3-Y),3) 把4加仑水壶中的水往3加仑水壶里倒,直至3加仑水壶装满为止;
7(X,Y|X+Y≤4∧Y>0)→(X+Y,0) 把3加仑水壶中的水全部倒进4加仑水壶里;
8(X,Y|X+Y≤3∧X>0)→(0,X+Y) 把4加仑水壶中的水全部倒进3加仑水壶里;
可能出现的操作为上面的8种情况
搜索策略:循环匹配→号左侧的情况,如果满足则进行右侧操作,直到搜索到目标状态或程序结束为止。
解决思路:采用模拟的方式遍历所有可能的结果,当找到目标则结束。其中需要记录已经搜寻过的状态,防止多次搜索同一状态陷入死循环。
大体流程:朝一个方向进行不断深入搜索,直到走到尽头,然后返回再进行搜索其他分支。(递归流程)
代码实现
# ######################################
# ## Author:Gu-f ##
# ## Time:2020/02/20 ##
# ######################################
# 当前大壶里面含有的水量
kettle_big = 0
# 当前小壶里面含有的水量
kettle_small = 0
# 大壶的容量
capacity_big = 4
# 小壶的容量
capacity_small = 3
# 目标大水壶水量
target_status = 2
# 已经存在过的状态
old_status = [[0,0]]
# back
back_kettle_big = 0
back_kettle_small = 0
# 状态备份
def back_kettle():
global back_kettle_small
global back_kettle_big
back_kettle_big = kettle_big
back_kettle_small = kettle_small
# 大小壶当前的状态
def kettle_status():
global kettle_big
global kettle_small
status = [kettle_big, kettle_small]
return status
# 倒满大壶
def full_big():
global capacity_big
global kettle_big
back_kettle()
kettle_big = capacity_big
check_kettle()
# 倒满小壶
def full_small():
global capacity_small
global kettle_small
back_kettle()
kettle_small = capacity_small
check_kettle()
# 清空大壶
def clear_big():
global kettle_big
back_kettle()
kettle_big = 0
check_kettle()
# 清空小壶
def clear_small():
global kettle_small
back_kettle()
kettle_small = 0
check_kettle()
# 小壶的水注满大壶
def small_to_big():
global kettle_big
global kettle_small
global capacity_big
back_kettle()
kettle_small = kettle_big + kettle_small - capacity_big
kettle_big = capacity_big
check_kettle()
# 大壶的水注满小壶
def big_to_small():
global kettle_big
global kettle_small
global capacity_small
back_kettle()
kettle_big = kettle_small + kettle_big - capacity_small
kettle_small = capacity_small
check_kettle()
# 小壶的水全部倒入大壶
def small_to_big_full():
global kettle_big
global kettle_small
back_kettle()
kettle_big = kettle_small + kettle_big
kettle_small = 0
check_kettle()
# 大壶的水全部倒入小壶
def big_to_small_full():
global kettle_small
global kettle_big
back_kettle()
kettle_small = kettle_big + kettle_big
kettle_big = 0
check_kettle()
# 检查是否查找过
def check_kettle():
global kettle_big
global kettle_small
if kettle_status() in old_status:
kettle_big = back_kettle_big
kettle_small = back_kettle_small
else:
if kettle_big == target_status:
print("\nFind answer!")
# print(old_status,end='')
old_status.append(kettle_status())
print("One of the methods found:")
for i in old_status:
print(i,end='')
print("-->",end='')
print("Finish!")
exit()
else:
old_status.append(kettle_status())
find_status()
# 递归查找存在可能使kettle_big = 2的情况,当查到任意一种情况后终止
def find_status():
global kettle_small
global kettle_big
if kettle_big < capacity_big or kettle_status() == [0,0]:
full_big()
if kettle_small < capacity_small:
full_small()
if kettle_big > 0:
clear_big()
if kettle_small > 0:
clear_small()
if kettle_small + kettle_big >= capacity_big and kettle_small > 0:
small_to_big()
if kettle_small + kettle_big >= capacity_small and kettle_big > 0:
big_to_small()
if kettle_small + kettle_big <= capacity_big and kettle_small > 0:
small_to_big_full()
if kettle_small + kettle_big <= capacity_small and kettle_big > 0:
big_to_small_full()
if __name__ == '__main__':
find_status()
print("Not Found!")
输出结果测试
大水壶容量:4
小水壶容量:3
目标大水壶水量:2
可行方法之一如下:
======================================
大水壶容量:4
小水壶容量:3
目标大水壶水量:1
可行方法之一如下:
======================================
大水壶容量:8
小水壶容量:7
目标大水壶水量:3
可行方法之一如下:
======================================
再附加一张画的连我自己都看不懂了的解释图,因为画的太烂,所以放最后吧。。。。。
红色箭头标注的为4,3,2样例的搜索流程(也就是输出结果第一个)