DFS 求解金字塔10*10等腰直角三角形摆放

115 篇文章 0 订阅
3 篇文章 0 订阅
# -*- coding:utf8 -*-
shape={
       0:[(0,0),(1,0),(1,1),(1,2)],
       1:[(0,0),(0,1),(1,0),(1,1),(1,2)],
       2:[(0,0),(1,0),(1,1),(1,2),(1,3)],
       3:[(0,1),(1,0),(1,1),(1,2),(1,3)],

       4:[(0,0),(0,1),(1,1),(1,2),(1,3)],
       5:[(0,0),(1,0),(1,1)],
       6:[(0,0),(1,0),(2,0),(2,1),(2,2)],
       7:[(0,0),(1,0),(1,1),(2,1),(2,2)],

       8:[(0,0),(0,1),(1,0),(2,0),(2,1)],
       9:[(0,0),(0,1),(0,2),(0,3)],
       10:[(0,0),(1,0),(1,1),(0,1)],
       11:[(1,0),(0,1),(1,1),(1,2),(2,1)],
}
allshape={}
field=[]
prepos=[]

def rotate(v, d):
       ibin=[0]*5
       rv0=max([vi[0] for vi in v])
       rv1=max([vi[1] for vi in v])
       dd=d/4
       d%=4
       ta= 1 if d<2 else -1
       tb= -1 if (d%2)==1 else 1
       for vi in v:
              v0= vi[0] if ta>0 else (rv0+vi[0]*ta)
              v1= vi[1] if tb>0 else (rv1+vi[1]*tb)
              v0,v1 = (v1,v0) if dd==1 else (v0,v1)
              ibin[v1] |= (1<<v0)

       vmap=reduce(lambda x,y: x|y, ibin)
       rot=0
       while vmap&(1<<rot)==0:
              rot+=1
       if rot>0:
              ibin=map(lambda x:x<<1, ibin)

       trim=0
       if ibin[trim]==0:
              trim+=1
       ibin=ibin[trim:]
       trim=0
       while trim<len(ibin) and ibin[trim]!=0:
              trim+=1
       return tuple(ibin[:trim])

def init():
       for k,v in shape.items():
              allshape[k]=set()
              for d in xrange(8):
                     ret=rotate(v, d)
                     allshape[k].add(ret)
class bcolors:
       block=['\033[91m','\033[92m','\033[93m','\033[94m','\033[95m',
              '\033[96m','\033[97m','\033[98m','\033[99m','\033[100m',
              '\033[90m','\033[89m' ]
       ENDC = '\033[0m'
       BOLD = '\033[1m'
       UNDERLINE = '\033[4m'

def dump(binmap, info, pos):
       print info
       print "^^"*5
       for b in binmap:
              print str(bin(b))[2:]
       print "**"*5
import unicodedata
def dumpput(blocks):
       fields=[' '*10]*10
       binfield=[0]*10
       for i,b in enumerate(blocks):
              for y,c in enumerate(b[0]):
                     binfield[b[2]+y]|=c<<b[1]
                     pos=0
                     while c>0:
                            if c&1 == 1:
                                   fields[b[2]+y] = fields[b[2]+y][:pos+b[1]] +  chr(ord('a')+i) + fields[b[2]+y][pos+b[1]+1:]
                            pos+=1
                            c>>=1
       for col,f in enumerate(fields):
              f=f[:col+1]
              for i in xrange(12):
                     f=f.replace(chr(ord('a')+i), ["❤️","?","?","?","?","?","?","?","?","?","?","?"][i])
              f=f.replace(' ','⭕')
              print f
       #
       # print "----"*4
       #
       # for f in binfield:
       #        print bin(f)[2:]
       print "===="*4
def addoneshape(target, current, used, shapeid, shape, pos):
       pass

def rmoneshape(current, used, shapeid, shape):
       pass

def tryfeed(targetmap, ks):
       feed=[0]*10
       check1=[0]*10
       check2=[0]*10
       bakcheck=[0]*10
       for i,onek in enumerate(ks):
           block=onek[0]
           x0=onek[1]
           y0=onek[2]
           for y,b in enumerate(block):
                  if y0+y>=10: return False
                  feed[y0+y] |= b<<x0
                  if i&1 == 0:
                      check1[y0+y] |= b<<x0
                      check2[y0+y] &= b<<x0
                  else:
                      check1[y0+y] &= b<<x0
                      check2[y0+y] |= b<<x0
           if i&1==0:
                  if check2!=bakcheck:
                         return False
           else:
                  if check1!=bakcheck:
                         return False
       if feed==targetmap:
           return True
       print feed
       return False
       
def checkfeed(target, feed, failedpos):
    cnt=0
    for f in feed:
           cnt+=1
           if cnt%1000000 == 0:
                 print cnt
           if tryfeed(target, f):
                  print f
    return None

def findhole(targetfield):
       lasth=[0]*12
       for i,v in enumerate(targetfield):
              if v<0:
                     v+=2**32
              lasth[i+1]=v<<1
              tmp=lasth[i]
              oldtmp=lasth[i]
              while tmp!=0:
                     tmp=tmp&(-tmp)
                     oldtmp-=tmp
                     #print "check:", tmp
                     tmp0=tmp<<1
                     tmp1=tmp>>1
                     tmp2=tmp>>2
                     tmp3=tmp>>3
                     if i>0:
                            if (tmp&lasth[i-1]) == 0 and (tmp&lasth[i+1])==0 and (tmp0&lasth[i])==0:
                                   if tmp1&lasth[i] == 0: return True
                                   if tmp2&lasth[i]==0 and tmp1&lasth[i-1]==0 and (tmp1&lasth[i+1])==0: return True
                                   if tmp3&lasth[i]==0 and tmp1&lasth[i-1]==0 and tmp1&lasth[i+1]==0 \
                                       and tmp2&lasth[i-1] and tmp2&lasth[i+1]: return True
                     if i>1:
                            if tmp&lasth[i-2]==0 and tmp&lasth[i+1]==0 \
                                and tmp0&lasth[i-1]==0 and tmp1&lasth[i-1]==0 \
                                and tmp0&lasth[i]==0 and tmp1&lasth[i]==0:
                                   return True
                     if i>2:
                            if tmp&lasth[i-3]==0 and tmp&lasth[i+1]==0 \
                                and tmp0&lasth[i-1]==0 and tmp1&lasth[i-1]==0 \
                                and tmp0&lasth[i-2]==0 and tmp1&lasth[i-2]==0 \
                                and tmp0&lasth[i]==0 and   tmp1&lasth[i]==0:
                                   return True
                     tmp=oldtmp

       return False


import itertools
maxdeep=0
def findans():
       targetfield=[]
       for i in xrange(0,10):
              targetfield.append(((1<<(i+1))-1))

       allshapes = allshape.values()
       print "try......", targetfield
       def putoneblock(targetfield, shapes, putblock):
              global maxdeep
              if len(shapes) == 0:
                     print putblock
                     return True
              if len(putblock)>maxdeep:
                     maxdeep=len(putblock)
                     if maxdeep>=10:
                            print putblock
                            dumpput(putblock)

                     print "deep:",maxdeep
              for s in shapes[0]:
                     for x in xrange(10):
                            for y in xrange(10):
                                   backfield=targetfield[:]
                                   passput=False
                                   for ybase,sc in enumerate(s):
                                          if y+ybase>=10:
                                                 passput=True
                                                 break
                                          checkv=targetfield[y+ybase]
                                          targetfield[y+ybase]^=sc<<x
                                          if checkv!=(targetfield[y+ybase]|sc<<x):
                                                 passput=True
                                                 break
215                                if not passput:
216                                       passput=findhole(targetfield)
                                   if passput:
                                          targetfield=backfield[:]
                                          continue
                                   putblock.append((s,x,y))
                                   putoneblock(targetfield, shapes[1:], putblock[:])
                                   del putblock[-1]
                                   targetfield=backfield[:]
              return False

       putoneblock(targetfield, allshapes, [])
       # ips=[]
       # for ip in allshape.values():
       #        ips.append(itertools.product(ip, range(10), range(10)))
       #
       # putpos=itertools.product(*ips)

       # ret=checkfeed(targetfield, putpos, failedpos)
       # return ret

init()
findans()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值