來自《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)