小项目-智慧金字塔求解器
Visolin
2026年08月11日 01:47
AI IN ALL!

事情起因


(一点碎碎念,技术向问题请参考OI-wiki,本篇仅注重于建模)

前几天我跟我初中同学出去打球,顺便出去搓一顿。三个男生自动刷新点子王,就聊到了ai。

我这个人是有一点嘉豪的,天天有事没事就喜欢瞎折腾,这AI也恰好撞到我舒适区了。正好饭桌上有个也喜欢研究钻研的理工男,我们俩很聊得来。我就和他从attention的QKV聊到harness,大谈特谈现在 AI 多强多nb。

ai统治人类!瘫坐在椅子上!仿佛看到原子弹爆炸!

我心满意足的回到家,又开始和hermes聊骚 (AI真的太好用了你知道吗)

聊着呢,他给我发了张照片——一个金字塔棋盘,上面放了两块积木。

聊天记录

我去,那我得坐起来和你打


心路历程

一拿到题目,我想着完鸟,这哪会做啊,AI这多模态能力也只能算是刚刚起步,这怎么可能会做。

抱着死马当活马医的态度,我把题交给hermes,果然,就算我换了国模最强视觉模型(截止写稿)Qwen3.7-plus和kimi-k2.6都试了一遍。国外御三家这套餐都超出我预算了,中转站怕投毒。我又不是刚需,还是老老实实用国内开源吧

得了,这省事的的方法来不了,那就只能来硬的了.

写个求解器,老手艺非遗古法编程,开搞!

对于一个求解器,那我们肯定先要还原这个游戏咯。创建一个棋盘class,里面包含一个原始棋盘的attribute,然后再加上下棋和检验合法位置的两个method。

头疼的来了,这个棋子,得要算上它所有的旋转以及翻折,这个情况就多得爆炸了。随便手画了一下,居然有50多种。这算一下得搞到猴年马月啊。


ai还是太好用了

对于这种比较复杂的东西,那我肯定不能重复造轮子。 其实是我懒 ,我决定先到网上去搜搜看,看看有没有现成的项目可以借鉴一下。面向github和CSDN编程(

现在AI虽然视觉不行,但是它长文本总结信息的能力还是很强的,它居然一下就找到了GitHub 上的远古秘境。解决的非常完美,深入研究以后,令我叹为观止。略微修改之后,我用python写了四个求解器


技术细节


积木的旋转翻折

如何表示一块积木呢?通过观察可知,最大的拼图块,范围也不会超过 4×4——那我们可以用 4×4 的二进制位图来表示它:4 个整数,每个代表一行 4 位,1 就是有珠子,0 就是空。

其实积木的旋转翻折,一共就那么多种情况,理论上你直接写死在这里也是可以的(反正也没多少)。但我们这里可以用一个更巧妙的方法——用算法把所有的变体生成出来,通过一些简单的坐标变换就能搞定。不过这是纯技巧性的东西,在此不多赘述。

生成完再遍历一遍、去去重,计算量能砍掉一大截。毕竟有些积木天生对称(正方形怎么转都是它自己,一字形翻过来还是它),不去重的话矩阵里全是重复行,白算,还容易产生bug,根据奥卡姆剃刀原理,全部删掉。


精确覆盖

先把算法放在一遍,先把这个问题想明白:这个问题的核心是什么?

回到拼图问题的本质:选几个放置方案,让每个格子恰好被覆盖一次、每块积木恰好被使用一次。

"恰好"就是精确覆盖的精髓——每个条件不多不少满足1次。

那么如何对其建模呢?其实一张表就足够了。

列 代表条件 一共 67 个:前 55 列是棋盘上 55 个格子(每个格子恰好被填一次),后 12 列是 12 块积木(每块恰好用一次)(当然你用按变体算也可以,那这个表会大很多,计算量就上去了)。行 代表放在哪个位置,放的是哪块,便在哪个各自上写 1

于是问题可以转化为:在这张几千行的 0-1 表里,遍历所有让每一列恰好有且仅有一个 1的可能。 之后的算法就变成了计算机最喜欢的暴力穷举环节了。

(第一次想通"55 个格子 + 12 块积木 = 67 个条件"的时候,我直拍大腿,妙,太妙了)

如何求解给定题目? 预置棋子就等于把某几行预先选中再求解,剩下照常遍历即可。


舞蹈链

表建好了,怎么搜索呢?

最朴素的是回溯:选一行 → 遍历 → 删掉所有跟它冲突的行 → 遍历 → 走不通就恢复再来。表一大,开销直接起飞。

这就是舞蹈链神奇的地方了:把这张表变成十字链表。每个节点上下左右四个指针,行串成环、列也串成环。删一行只要动两根指针跳过去,恢复时因为横向关系一直存在,只需要再横向遍历一遍并用竖向链表恢复就可以完美复原,这只是简单的变下指针指向的下一个值而已,做到了O(1)!指针在链表里跳来跳去跟跳舞一样, Dancing Links便由此得名。

(我从一开始学算法的不理解为什么这么麻烦要搞出链表这么个麻烦的东西,改起来多写好几行,iterator还只能用一次,这几个暂存的节点指来指去头都大死了,全列表不久完了吗。现在才知道他的神秘大用)

原理我本来想写的,但在找材料的时候发现 OI Wiki 讲得比我好一万倍,不重复了。那就说说我的实现吧:

  • 数组模拟十字链表 —— Python 并没有指针,但可以用数组下标代替

  • 启发式选列 —— 每次挑"当前 1 最少"的列下手,搜索树直接砍掉一大截

  • 并行——先用广度优先把搜索树展开 3 层,拆成几十个子问题,然后深度优先多核一人算一个走到头,快速出结果。


结果


我的笔记本是 i5-6300HQ,好几年前的老东西了。Python 又是出了名的慢。不过我相信这现代cpu的算力,力大飞砖。

三角形棋盘——109.6 秒,32,288 种解法。

三万多。做出来一种我都就觉得自己牛逼坏了——现在计算机可以精确地告诉你还有三万多条路你没走过,每种都是什么样的,保存下来的文件也才几KB,顿时感到现代计算机的强劲。

5 层立体金字塔——95.9 秒,2,448 种。

矩形棋盘——解太多了,没等它跑完。

如果只找一个解——0.1 秒。回车按完就出答案了,还是太强了。

神秘小感想


好久以前就有人在琢磨精确覆盖了。然后高德纳搞出了 Dancing Links。九年前有人写了 C++ 版。再到用 Python、用 AI 把它重写了一遍,思考一代一代的传播下去。

这些数学思想不会过时,它们只是在等合适的工具、合适的时机,被重新捡起来。

放在几年前,你想完全搞明白底层原理,得会 C++、懂算法、能调优。现在嘛,你只需要愿意去琢磨,有一颗探索的心,路就在前方。

AI 把解决问题的门槛压得很低了。但也正因为这样 —— 独立思考反而比以前更重要。AI 能帮你写代码,但不能替你对这个世界「哎?」那一下。

那同学四岁时收到的礼物,十多年后终于有答案了。


参考:github.com/zigzag2050/IQPyramidSolver​ · https://oi-wiki.org/search/dlx/

代码:Claude Code · deepseek-v4-pro

设备:i5-6300HQ · Python · 32,288 / 2,448 / 0.1s

项目:github.com/Visol-456/IQPyramidSolver-Python​