python 处理八数码 双向BFS 拼图游戏

我的代码一开始是单向的BFS
然后很慢,5分钟?
参照别人的代码后,改用双向BFS
很快


拼图问题 == 八数码问题




算法思想

从开始状态start,进行BFS
同时,从结束状态end,进行BFS
如果左图能够转成右图,那么一定会在某一时刻,存在一个中间接口状态,既在开始状态开始的BFS的队列中,又在结束状态开始的BFS的队列中

Ps:顺便吐个槽,python的return,返回一个元组,很好使


代码

# -*- coding: cp936 -*-
import sys

def getPos(m):
    for i in range(len(m)):
        if m[i] == 9 :
            return i
        
def result(state,cache,l,r):
    for i in range(l,r):
        if state == cache[i]:
            return i
    return -1

step = 0

def print_after(cache,far,num):#print 后序
	if num==-1:
		return
	print_after(cache,far,far[num])
	print(cache[num])
	global step
	step+=1


def printf_before(cache2,far2,num):#print 前序
    if num == -1:
        return
    print(cache2[num])
    printf_before(cache2,far2,far2[num])
    global step
    step += 1
    
def do_with(cache,cache2,far,l,r,l2,r2):
    flag = 0
    t = cache[l]
    
    #得到9所在的行列数x,y
    pos = getPos(t)
    x,y = divmod(pos,3)

    #四个方向,四种新状态
    newpos = []
    if y < 2:newpos.append(pos+1)
    if y > 0:newpos.append(pos-1)
    if x < 2:newpos.append(pos+3)
    if x > 0:newpos.append(pos-3)
    for ipos in newpos:
        tt = cache[l][:]
        tt[ipos]=cache[l][pos]
        tt[pos]=cache[l][ipos]

        #如果新状态没在cache中就加入cache,队列尾巴r+1
        if tt not in cache:
            cache.append(tt)
            far.append(l)
            r += 1
            #如果新状态在逆向的cache2中找到,那么新状态就是接口状态
            #找到接口状态就可以直接打印了,返回接口状态的下标res,赋值给flag
            res = result(tt,cache2,l2,r2)
            if res != -1:
                flag = res
    l += 1
    return cache,cache2,far,l,r,l2,r2,flag

def do_with_print(before,after):
    print_after(cache,far,before)
    printf_before(cache2,far2,far2[after])#如果这里不用far2[flag]而用flag就重复计算中间的接口状态
    print step-1 #减去一开始的状态不计算步数
    sys.exit(0)
    
start = [1,2,3,4,5,6,7,8,9]
end   = [9,8,7,6,5,4,3,2,1]

cache = [start] #保存正向状态
cache2 = [end]  #保存逆向状态
far = [-1]      #保存正向状态的left节点下标     
far2 = [-1]     #保存逆向状态的left节点下标

l = l2 = 0
r = r2 = 1


while (l!=r)and(l2!=r2):      #BFS,left == right表示队列为空
    flag = -1 #保存中间接口状态的下标
    cache,cache2,far,l,r,l2,r2,flag = do_with(cache,cache2,far,l,r,l2,r2)
    if flag:
        do_with_print(r-1,flag)
    cache2,cache,far2,l2,r2,l,r,flag = do_with(cache2,cache,far2,l2,r2,l,r)
    if flag:
        do_with_print(flag,r-1)



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值