史上最难数独求解,用时约5秒,回溯法,deepcopy是关键

来源:互联网 发布:孙杨 宁泽涛 知乎 编辑:程序博客网 时间:2024/05/17 05:06
from copy import deepcopyfrom time import clockposinfo0={(0,0):8,         (2,1):3,(3,1):6,         (1,2):7,(4,2):9,(6,2):2,         (1,3):5,(5,3):7,         (4,4):4,(5,4):5,(6,4):7,         (3,5):1,(7,5):3,         (2,6):1,(7,6):6,(8,6):8,         (2,7):8,(3,7):5,(7,7):1,         (1,8):9,(6,8):4,         }posb0={}def init(posb, posinfo):    for i in xrange(0,9):        for j in xrange(0,9):            if (i,j) not in posinfo:                posb[(i,j)]=[n for n in xrange(1,10)]    for pos in posinfo:        cleanother(0,pos[0],pos[1],posinfo[pos],posb,posinfo)def checkpos(posb, posinfo):     posb1=posb.copy()    posinfo1=posinfo.copy()    ret=0    for pos in posb:        if len(posb1[(pos[0],pos[1])])==1:            addinfo(pos[0],pos[1],posb1[(pos[0],pos[1])][0],posb1,posinfo1)            ret=1            break                    elif len(posb1[(pos[0],pos[1])])==0:            ret=2            break    posb=posb1    posinfo=posinfo1    return retdef cleanother(mod,x,y,v,posb,posinfo):    posb1=posb.copy()    x0=x/3*3    y0=y/3*3        for ii in xrange(0,3):        for jj in xrange(0,3):            if (x0+ii,y0+jj) in posb:                 if v in posb1[(x0+ii,y0+jj)]:                    posb1[(x0+ii,y0+jj)].remove(v)                        for ii in xrange(0,9):        if (ii,y) in posb:             if v in posb1[(ii,y)]:                posb1[(ii,y)].remove(v)                    for jj in xrange(0,9):        if (x,jj) in posb:             if v in posb1[(x,jj)]:                posb1[(x,jj)].remove(v)    ret=0    if posb1!=posb:        ret = checkpos(posb1,posinfo)        posb=posb1    return retdef findmin(posb):    minv=9    minpos=(0,0)    for key,val in posb.items():        if minv>len(val):            minv=len(val)            minpos=key    return (minv,minpos)def outputInfo(posinfo):    print "\n   %s"%" ".join(str(v) for v in xrange(0,9))    print "-----------"*2    for i in xrange(0,9):        print "%d|"%i,        for j in xrange(0,9):            if (j,i) in posinfo:                 print posinfo[(j,i)],            else:                print " ",        print    print "==========="*2    def addinfo(x,y,v,posb,posinfo):    if (x,y) in posinfo:return     #print "addinfo",x,y,v    if (x,y) in posb:         del posb[(x,y)]    posinfo[(x,y)]=v    clearallinfo(posb,posinfo)    #outputInfo(posinfo)    def clearallinfo(newposb, newposinfo):    newposinfo2=newposinfo.copy()    for pos in newposinfo:        cleanother(0,pos[0],pos[1],newposinfo[pos],newposb,newposinfo2)    if newposinfo2==newposinfo: return    newposinfo=newposinfo2    #print "newposinfo"    #outputInfo(newposinfo)    clearallinfo(newposb, newposinfo) def tryonestep(minpos, posb, posinfo, layer):    global tic    for posbv in posb[minpos]:        newposb=deepcopy(posb)        newposinfo=posinfo.copy()        addinfo(minpos[0],minpos[1],posbv,newposb,newposinfo)        #print posb[minpos], newposb[minpos]        #outputInfo(newposinfo)        minv2,minpos2=findmin(newposb)        #outputInfo(newposinfo)                #print minpos2, newposb[minpos2]        if minv2==0:            #print "impossible!!!", layer            continue        if len(newposb)==0:            print "Got it!!!"            outputInfo(newposinfo)              print "elapsed:", clock()-tic            exit(0)        tryonestep(minpos2, newposb, newposinfo, layer+1)    
    tic=clock() init(posb0, posinfo0) minv,minpos=findmin(posb0)    print "start===>"outputInfo(posinfo0)newposb=posb0.copy()newposinfo=posinfo0.copy()tryonestep(minpos, newposb, newposinfo, 0)print "No answer!!"

原创粉丝点击