水壶问题 python实现倒水操作

题目

给定两个水壶,一个可装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样例的搜索流程(也就是输出结果第一个)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值