三个杯子的倒水问题(BFS)

三个杯子的倒水问题(BFS)

'''
已知容积为160 119 77的空桶和无限多的水
想要得到76升的水
问需要多少次操作?
'''
import numpy as np
##################################
visited = np.zeros((200,200,200))#对被访问过的进行记录,取决于空桶的最大容积
##################################

class cup(object):
    '''
    定义量杯类
    '''
    def __init__(self,name,volume,MaxV):
        self.name = name
        self.MaxV = MaxV
        self.volume = volume
        
A = 160#三个杯子的最大容量
B = 119
C = 77
#默认 杯中为空
Result = 76  # 目标
cupA = cup('A', 0, A)
cupB = cup('B', 0, B)
cupC = cup('C', 0, C)

def XpourWaterToY(cupX,cupY):
    '''
    把X中的水倒入Y中
    :param CupX: 
    :param cupY: 
    :return: surplusX:X中的剩余量
            surplusY:Y中的剩余量
    '''
    if cupX.volume >= cupY.MaxV-cupY.volume:#如果X中的液体容量,比Y的最大容量-现有溶液体积的话
        cupX.volume = cupX.volume - (cupY.MaxV-cupY.volume)#此时X中剩余水的体积
        cupY.volume = cupY.MaxV  # 那么Y被倒满水
    else:
        cupY.volume = cupY.volume + cupX.volume  # X中的水全部倒入Y
        cupX.volume = 0 #X中的水被倒光了
    return cupX.volume,cupY.volume

def emptyWater(cupX):
    '''
    把X中的水清空,倒入水池中(不倒入任何容器)
    :param cupX:
    :return:
    '''
    cupX.volume = 0
    return 0

def fillWater(cupX):
    '''
    将X倒满水
    :param cupX:
    :return:
    '''
    cupX.volume = cupX.MaxV
    return cupX.volume

def show():
    '''
    当前三个水杯的状态
    :return:
    '''
    return cupA.volume,cupB.volume,cupC.volume

class State:
    def __init__(self,a,b,c,prev=None,step=0):
        self.a = a
        self.b = b
        self.c = c
        self .prev = prev
        self.step = step

def bfs(cupA,cupB,cupC,Result):
    queue = []
    s = State(cupA.volume,cupB.volume,cupC.volume)
    queue.append(s)
    visited[0][0][0]=1
    while queue:
        statu = queue.pop(0)
        flag = 1 #计数 , 因为有三个水杯且无限的水 所以有12种生成新节点的方式
        while flag < 13:#让每个节点对每种情况都生成新的节点,并进行判断
            cupA.volume = statu.a
            cupB.volume = statu.b
            cupC.volume = statu.c
            #在每次生成新节点时,让杯中的状态回到父节点状态
            a,b,c = 0,0,0
            if flag == 1 :
                emptyWater(cupA)
                a,b,c = show()

            if flag == 2:
                emptyWater(cupB)
                a,b,c = show()

            if flag == 3:
                emptyWater(cupC)
                a,b,c = show()

            if flag == 4:
                fillWater(cupA)
                a,b,c = show()

            if flag == 5:
                fillWater(cupB)
                a,b,c = show()

            if flag == 6 :
                fillWater(cupC)
                a,b,c = show()

            if flag == 7:#把A倒入B
                XpourWaterToY(cupA,cupB)
                a,b,c = show()

            if flag == 8:#把B倒入A
                XpourWaterToY(cupB,cupA)
                a,b,c = show()

            if flag == 9:#把A倒入C
                XpourWaterToY(cupA,cupC)
                a,b,c = show()

            if flag == 10:#把C倒入A
                XpourWaterToY(cupC,cupA)
                a,b,c = show()

            if flag == 11:#把C倒入B
                XpourWaterToY(cupC,cupB)
                a,b,c = show()

            if flag == 12:#把B倒入C
                XpourWaterToY(cupB,cupC)
                a,b,c = show()

            if not visited[a][b][c]:#判断是否生成过
                new_state = State(a,b,c,prev=statu,step=statu.step+1)
                visited[a][b][c] = 1
                queue.append(new_state)
                if a == Result or b == Result or c == Result:#判断是否满足目标条件
                    print("Find!")
                    return new_state
            flag += 1
    return None

def getPath(state):#获取路径 由目标节点向其父节点回溯
    path = []
    while state.prev :
        path.append(str(state.step)+' '+str((state.a,state.b,state.c)))
        state = state.prev
    return path[::-1]#逆序

def main():
    '''
    主函数
    '''
    reslut = bfs(cupA, cupB, cupC, Result)
    path = getPath(reslut)
    print('三个量杯最大容积为' + str((cupA.MaxV, cupB.MaxV, cupC.MaxV)))
    print('目标水体积' + str(Result))
    print('Path:' + '\n' + '共用了' + str(len(path)) + '步')
    for i in path:
        print(i)
if __name__ == '__main__':
    main()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值