三商人三仆人过河问题

'''三商人三仆人过河问题,有一条船,最多只允许乘2人,要求商人数不少于仆人数,

设计过河方案'''
'''基于状态空间搜索,深度优先搜索'''

test=[[True,True,True,True],##### 状态允许,作为检验下一步的依据
      [True,True,False,False],
      [True,True,True,False],
      [True,True,True,True]]
###有效的操作
dirs=[[1,1],[0,2],[0,1],[1,0],[2,0]]

start=[3,3,1]###开始状态
end=[0,0,0]###结束状态

list2=[start]
###mark函数用于标记已经存在的状态,如果这个状态可行,加入list2中。
def mark(nextp):
    list2.append(nextp)
    return True
#######判断解的可行性,如果可行,加入栈中
def passable(nextp):
    k=[]
    a=[3-nextp[0],3-nextp[1]]
    for i in a:
        if i<0 or i>3:
            return False
    if test[a[0]][a[1]] and test[nextp[0]][nextp[1]]:
        if nextp not in list2:
            return True
        else:
            return False
            
#####主函数   
def solver(start,end):
    if start==end:
        print(start)
        return
    stack=[] #建立栈
    stack.append((start,0)) #放入初始状态
    while stack:
        n=len(stack)
        #nxt 记录记录方向
        pos,nxt=stack.pop()
        ####   5表示操作数
        for i in range(nxt,5):
            '''计算下一步,n是栈的长度,n为奇数,表示过河,n为偶数,表示将船返回'''
            nextp=[pos[0]+pow(-1,n)*dirs[i][0],pos[1]+pow(-1,n)*dirs[i][1],(n+1)%2]
            ####搜索结束的条件
            if nextp==end:
                stack.append((nextp,0))
                print('问题解决')
                return stack
            ####判断解是否可行
            if passable(nextp):
                ###如果可行,将原状态先放入栈中,并将 方向+1
                stack.append((pos,i+1))
                ###标记解,防止无限循环
                mark(nextp)
                ###将下一状态放入栈中
                stack.append((nextp,0))
                ###结束循环
                break
            
st=solver(start,end)
for i in st:
    print('左岸商人数: %d'%i[0][0],'左岸仆人数: %d'%i[0][1])

print('全部过河,共%d步'%len(st))


运行结果:

问题解决
左岸商人数: 3 左岸仆人数: 3
左岸商人数: 2 左岸仆人数: 2
左岸商人数: 3 左岸仆人数: 2
左岸商人数: 3 左岸仆人数: 0
左岸商人数: 3 左岸仆人数: 1
左岸商人数: 1 左岸仆人数: 1
左岸商人数: 2 左岸仆人数: 2
左岸商人数: 0 左岸仆人数: 2
左岸商人数: 0 左岸仆人数: 3
左岸商人数: 0 左岸仆人数: 1
左岸商人数: 0 左岸仆人数: 0
全部过河,共11步
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值