目录

  • 前言
  • 一、解决思路
    • 1.1. 解决思路
    • 1.2 存在问题
    • 1.3 解决方法
  • 二、问题解决
    • 1. 积木抽象
    • 2. 计算孔洞数量
  • 3. 主程序
  • 4. 部分结果展示
  • 总结

前言

“伤脑筋十三块”,又被称为“八阵图”,这款玩具基于“伤脑筋十二块”的基础上,将其可玩性、多变性升华到了极致。
“伤脑筋十三块”既具备了一共有16146种平面装法(翻转、旋转均算一种),假若将十三块积木置于方盒之外,可以拼成汉字、动物、建筑物等等任何您所能想象到的物体,玩法更是不计其数,这就是“伤脑筋十三块”的微妙之处:玩物知志、寓教于乐!

一、解决思路

1.1. 解决思路

  1. 遍历所有可能的排列
  2. 对所有的组合进行验证,去除所有不能完美放入盒子的排列

1.2 存在问题

全部可能的排列一共13!(6227020800)种,每种排列又有2*45*85(67108864)种旋转、翻转状态,共计87756541318397952000(8.77×1019)各排列,根本无法在有限时间内全部验证可行性

1.3 解决方法

按遍历顺序,每块各种依次填入空格中,每增加一块积木,验证可行性,如果内部存在不可填充满的空隙、或者内部存在重叠区域,那么以前面几块积木开始的所有排列都是不可行,可以直接跳过,这样可以大大减小验证次数。

二、问题解决

1. 积木抽象

将所有积木简化成一个最小的二维矩阵,空的地方是0,实的地方置1,为简化计算,全部转化成numpy数组
文件名:config.py,代码如下:

import numpy as npparts = [[[1, 1, 1, 1], [1, 0, 0, 0]], [[1, 1], [1, 1], [1, 0]], [[1, 1, 1, 1], [0, 1, 0, 0]], [[1, 1, 1, 1, 1]], [[1, 0, 0], [1, 1, 0],[0, 1, 1]], [[1, 0, 0], [1, 1, 1], [1, 0, 0]], [[1, 1, 0], [0, 1, 1],[0, 1, 0]], [[1, 1], [1, 1]],[[1, 1, 0], [0, 1, 0], [0, 1, 1]], [[0, 1, 0], [1, 1, 1], [0, 1, 0]], [[1, 1, 1], [1, 0, 0], [1, 0, 0]], [[0, 1], [1, 1], [1, 0], [1, 0]], [[1, 1], [1, 0], [1, 1]], ]
parts = [np.array(i, dtype=np.uint8) for i in parts]

2. 计算孔洞数量

每增加一块积木都计算一次孔洞个数,及每个孔洞内孔0的个数,如果所有孔洞内0的个数都能被5整除或被5除余4,那可能是可行解,否则一定是不可行解,返回False,提前结束后续遍历
文件名:findhole.py,代码如下:

import numpy as npdef findhole(arr):possible = {4,5,9,10,14,15,19,20,24,25,29,30,34,35,39,40,44,45,49,50,54,55,59,60,64}x, y = np.where(arr==0)#print(x)#print(y)rdt = {}cdt = {}for i, j in zip(x, y):rdt.setdefault(i, set())rdt[i].add(j)cdt.setdefault(j, set())cdt[j].add(i)#print('rdt:', rdt, sep='\n')#print('cdt:', cdt, sep='\n')res = set()for i, j in zip(x, y):if not j in rdt.get(i, {}):continuehole = {(i,j)}queue = {(i,j)}used = set()while queue:x0, y0 = queue.pop()rdt[x0].discard(y0)used.add((x0, y0))for dx, dy in zip([0,0,-1,1],[-1,1,0,0]):x, y = x0+dx, y0+dyif y in rdt.get(x, {}):if (x,y) in used:continuequeue.add((x, y))hole.add((x, y))#res.add(hole)if not len(hole) in possible:return False, len(hole)return True, 0

3. 主程序

采用递归法遍历所有可行解,当递归深度达到13时,刚好将所有积木填入盒中,如果能够同时满足孔洞个数是0,并且没有重叠时,说明该排列符合要求,输出结果,为便于分辨积木,将不同形状积木编号,每块积木对应位置输出积木号码

文件名:main.py,代码如下:

import numpy as np
import time
from config import parts
from findhole import findholedef getPos(arr, flip=1):lt = []for i in range(4):lt.append(np.rot90(arr, i))if not flip:continuelt.append(np.rot90(arr.T, i))dt = {}for i in lt:dt[str(i.tolist())] = ilt = list(dt.values())return ltdef showall(parts):arr = np.zeros([8,8], dtype=np.uint8)#arr[:2, :2] = 13#arr[0, 2:7] = 12for i, part in enumerate(parts):val = mapping.get(str(part), 111)*16ret = check(arr, part, val)return True, arr//16def check(arr, part, out=0):#print(arr)#print(part)m, n = part.shapex0, y0 = np.where(part==1)x, y = np.where(arr==0)x, y = x[0], y[0]-y0[0]##print('part:\n', part)if y<0:#print('out of arr left')return False, arrif y+n>8:#print('out of arr right')return False, arrif x+m>8:#print('out of arr bottom')return False, arrtmp = arr[x:x+m, y:y+n]##print('tmp:\n', tmp)if out:#print('temp:', tmp, sep='\n')#print('part:', part, sep='\n')tmp += part*outelse:tmp += partif tmp.max()>1:#print('coincide')return False, arr##print(m, n, x, y, x0[0], y0[0])return True, arrdef merge(used, length, lt, arr, deep=0):ret, num = findhole(arr)if not ret:returnif deep>12:print(f'deep: {deep}')print(showall(result[:deep+1])[1])#print(arr)returnfor i8 in range(length):if i8 in used:continueused.add(i8)for j, p8 in enumerate(lt[i8]):result[deep] = p8#print(arr)arr2 = arr.copy()ret, arr3 = check(arr2, result[deep])if not ret:continueif deep<4:print(time.strftime('%H:%M:%S'), f"deep:{deep} i:{i8} j:{j}", *used)merge(used, length, lt, arr2, deep+1)used.remove(i8)
if __name__=='__main__':length = 13np.random.shuffle(parts)lt = [getPos(i) for i in parts]#lt.sort(key=lambda i: len(i))#print(*[j for i in lt for j in i], sep='\n\n')flag = Trueprint(*[len(i) for i in lt])for i, items in enumerate(lt):if flag and len(items)==8:lt[i] = items[:1]flag = Falseprint('only')print(*lt[i], sep='\n', end='\n\n')print(*[len(i) for i in lt])mapping = {str(k):(i+1) for i, j in enumerate(lt) for k in j}used = set()arr = np.zeros([8,8], dtype=np.uint8)ret, arr = check(arr.copy(), parts[0])result = list(range(length))#exit(0)arr = np.zeros([8,8], dtype=np.uint8)merge(used, length, lt, arr)

4. 部分结果展示


总结

以上是遍历法解决伤脑筋十三块的全部,有什么问题欢迎提出改进意见,可以直接留言或发邮件,邮箱:zhyh55@163.com
如果有什么难题,好玩的、需要用程序解决的也可以分享,一起解决

python遍历法解决伤脑筋的十三块全部可行解相关推荐

  1. 八皇后问题python回溯_解决Python基于回溯法子集树模板实现8皇后问题

    这篇文章主要介绍了Python基于回溯法子集树模板实现8皇后问题,简单说明了8皇后问题的原理并结合实例形式分析了Python回溯法子集树模板解决8皇后问题的具体实现技巧,需要的朋友可以参考下 本文实例 ...

  2. “马的遍历”问题的贪婪法解决算法

    /**//*    标题:<<系统设计师>>应试编程实例-[递推算法程序设计]     作者:成晓旭     时间:2002年09月14日(18:20:00-20:18:00) ...

  3. 《贝叶斯思维:统计建模的Python学习法》——2.3 贝叶斯框架

    本节书摘来异步社区<贝叶斯思维:统计建模的Python学习法>一书中的第2章,第2.3节,作者:[美]Allen B. Downey,更多章节内容可以访问云栖社区"异步社区&qu ...

  4. 07. 实战:Python正则法抓取某网站2022必看片迅雷种子

    目录 前言                URL(在评论区)URL(在评论区)URL(在评论区) 目的                URL(在评论区)URL(在评论区)URL(在评论区) 思路    ...

  5. Python遍历字典、集合与函数

    Python遍历字典.集合与函数 一.遍历字典 代码块 意义 keys() 该⽅法返回字典所有的key values() 该⽅法返回⼀个序列,序列中保存有字典的值 items() 该⽅法会返回字典中所 ...

  6. 站长在线经典Python题:使用Python编程思想解决鸡兔同笼的问题的4种方法

    欢迎你来到站长在线的Python题库,鸡兔写完Python教程以后,还是来一个Python的题目吧!想来想去,还是写一个经典的题目为好,作为本栏目的第一个题目.我就想到了比较热门的题目<鸡兔同笼 ...

  7. python遍历文件目录_python目录遍历

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 我曾经写了c语言的遍历目录.php的遍历目录,今天来说一下python遍历目录, ...

  8. 回溯算法背包问题迭代c语言,回溯法解决0_1背包问题(迭代和递归)

    问题:0/1背包问题 例子:weight数组代表物品重量,value数组代表物品价值,M代表背包容量.背包是按单位价值递减的顺序排列的,即value[i]/weight[i]>value[i-1 ...

  9. 利用回溯法解决1-9之间添加+或-或使得运算结果为100的问题

    问题描述 编写一个在1,2,-,9(顺序不能变)数字之间插入+或-或什么都不插入,使得计算结果总是100的程序,并输出所有的可能性.例如:1 + 2 + 34 – 5 + 67 – 8 + 9 = 1 ...

最新文章

  1. 什么叫大地高_续航8折不存在,北汽新能源EX5实力演绎什么叫高续航SUV!
  2. c# combobox集合数据不显示_VBA与数据库解决方案:Recordset记录集合的动态查询,并显示结果...
  3. X11硬线接口信号 与Profisafe安全输入输出信号之间的区别与比较
  4. Android 5.1 - 状态栏充电标志问题
  5. Top 10 Project Management Software
  6. LeetCode 1237. 找出给定方程的正整数解
  7. 官网mysql安装目录_官网下载MySQL 并安装
  8. Python pow() 函数
  9. 微信公众号H5支付遇到的那些坑
  10. Unicode官网Code Charts下载。
  11. Java 爬虫系列丨(一)爬虫介绍
  12. QT--3.创建一个简单的图形界面
  13. R语言——查看内置数据集
  14. 软件工程及软件生命周期
  15. 二分法查找(dichotomy)--python实现
  16. 【Android】Android模拟器的安装
  17. Latest SoC
  18. 大数据之保险行业的领导驾驶舱到底怎么做!附上模板
  19. mysql中用于删除数据的是什么意思_从mysql中删除数据最安全的方法是什么? (PHP / MySQL的)...
  20. 非域环境下搭建文件服务器,非域环境下SQL Server搭建Mirror(镜像)的详细步骤...

热门文章

  1. linux 生成随机文件,Linux 批量创建文件,文件名随机取
  2. Mac电脑如何快速提取图片的文字?
  3. java与python之间的混合开发
  4. 米家机器人连接不上了怎么重置_米家扫地机器人怎么重置wifi_米家扫地机器人wifi怎么重置...
  5. 为什么越来越多的访问学者去加拿大访学?
  6. codeforces 706 div2题解
  7. 信息学奥赛一本通:1169:大整数减法
  8. 45套(毕业答辩、开题报告、职场)PPT模板免费赠送
  9. 24口交换机SYNC模块学习
  10. xshell 隧道 mysql_u盟及xshell的mysql或redis隧道的配置等-------windows