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

from copy import deepcopy
from time import clock

posinfo0={(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 ret

def 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 ret


def 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!!"

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值