来自《Lua程序与设计》第二节- 八皇后问题数组
书中提供的源代码,加注了本身的注释。编辑器
N = 8 --[[ N为棋盘规模 a为一维数组,保存第i个皇后所在的列数 ]] -- 检查是否能够将第n个皇后放在第n行第c列(前n-1行的皇后已经放好) function isplaceok(a,n,c) -- 检查前n-1个皇后是否与(n,c)位置冲突 for i = 1, n - 1, 1 do if a[i] == c or -- 是否同一列 a[i] - i == c - n or --是否同一对角线 (?) a[i] + i == c + n then --是否同一对角线 (?) return false end end return true -- 不会被攻击 位置有效 end -- 用于在找到解后打印棋盘 function printsolution(a) for i = 1, N do for j = 1, N do io.write(a[i] == j and "X" or "-", " ") end io.write("\n") end io.write("\n") end -- 已经找到前n-1皇后的位置 -- 存放于a中 -- 寻找第n个皇后可摆放的位置 function addqueen(a,n) if n > N then printsolution(a) return true else -- 逐列检查可否摆放第n个皇后 for c = 1, N do if isplaceok(a, n, c) then a[n] = c if addqueen(a, n+1) then return true end end end end end -- 启动方式 addqueen({}, 1)
修改addqueen函数便可。函数
-- 已经找到前n-1皇后的位置 -- 存放于a中 -- 寻找第n个皇后可摆放的位置 function addqueen(a,n) if n > N then printsolution(a) return true else -- 逐列检查可否摆放第n个皇后 for c = 1, N do if isplaceok(a, n, c) then a[n] = c if addqueen(a, n+1) then return true end end end end end
必定是本来的方法效率更高…1-8之间的全部排列一共有8的8次幂个,检查每一个排列是否合法又是O(n^2)的复杂度,效率会很低。只看isplaceok函数调用次数的话,原来的方法一共调用isplaceok函数876次,生成全部排列的方法生成了8的8次幂个排列,每一个排列调用isplaceok的次数最少1次,最多8次,总体也在5千万次以上。
实际测了一下,用的在线编辑器,直接爆掉了。又从新用本地的lua跑了一下。调用isplaceok的次数为50889536次。(妈呀)性能
N = 8 --[[ N为棋盘规模 a为一维数组,保存第i个皇后所在的列数 ]] count = 0 -- 检查是否能够将第n个皇后放在第n行第c列(前n-1行的皇后已经放好) function isplaceok(a,n,c) count = count + 1 -- 检查前n-1个皇后是否与(n,c)位置冲突 for i = 1, n - 1, 1 do if a[i] == c or -- 是否同一列 a[i] - i == c - n or --是否同一对角线 (?) a[i] + i == c + n then --是否同一对角线 (?) return false end end return true -- 不会被攻击 位置有效 end -- 用于在找到解后打印棋盘 function printsolution(a) for i = 1, N do for j = 1, N do io.write(a[i] == j and "X" or "-", " ") end io.write("\n") end io.write("\n") end -- 已经放置前n-1皇后 -- 存放于a中 -- 放置第n个皇后 function addqueen(arrays, a, n) if n > N then table.insert(arrays, a) else -- 逐列检查可否摆放第n个皇后 for c = 1, N do local b = {} for k, v in pairs(a) do b[k] = v end b[n] = c addqueen(arrays, b, n+1) end end end function getsolution() local posibles = {} addqueen(posibles, {}, 1) for _, v in pairs(posibles) do local ok = true for i = 1, N do ok = isplaceok(v, i, v[i]) if not ok then break end end if ok then printsolution(v) end end end -- 启动方式 getsolution() io.write("\n",count)