穷举法可以解决很多问题,当数据规模变大时,需要一些优化技巧,剪枝就是一个常用手段,穷举+剪枝就是回溯算法了。
数独游戏,一行代码搞定N皇后问题,0.1秒玩胜Matlab之父Cleve Moler的四阶幻方!
在Wolfram Mathematica中处理这类问题很简洁,常用写法是排列组合函数(Tuples、Permutations、Subsets等)配合Select,或者使用列表操作进行迭代,经常两三行就能解决问题。不过也有缺点,这些排列组合函数是一次性生成一个大列表不是惰性求值,数据规模一大甚至会耗尽内存,速度也不一定快。
如果要换一种写法,自然就会想到使用(多重)循环或递归了,Mathematica中循环的效率不算高,但是可以配合编译(Compile)来大幅加速。比起递归,多重循环其实更容易被编译器优化,多数编程语言中,层数很多的循环再层层嵌套If,写起来麻烦,看起来实在感人,可扩展性也差,通常要避免。不过Mathematica具备像LISP中“数据即代码,代码即数据,一切都是表达式”和擅长符号计算等特性,我们可以很方便的进行元编程(Meta-Programming),通过写代码来动态生成代码再编译,从而对程序加速,有时可以接近C语言的速度。