• Lua实现的八皇后问题


    来自《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("
    ")
        end
        io.write("
    ")
    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)
    

    书后练习

    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
    
    2. 解决八皇后问题的另一种方式是,先生成1-8之间的所有排列,然后依次遍历这些排列,检查每一个排列是否是八皇后问题的有效解。请使用这种方法修改程序并对比性能差异。

    一定是原本的方法效率更高…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("
    ")
     end
     io.write("
    ")
    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("
    ",count)
    
  • 相关阅读:
    2019春总结
    2019春第一周编程总结
    第十二周
    2019春第七周编程总结
    2019春第四周作业
    人生路上对我影响最大的三位老师
    第五周课程总结&试验报告(三)
    第四周课程总结&试验报告(二)
    第三周课程总结&实验报告一
    第二周java学习总结
  • 原文地址:https://www.cnblogs.com/zoey-liao/p/12271166.html
Copyright © 2020-2023  润新知