8皇后问题 回溯 递归 代码实现

8皇后问题 回溯 递归 代码实现

算法

  • 如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。
  • 8皇后回溯算法
    • 定义a[k] = i:第k个皇后放在第 k行,第 i列
    • 皇后从第一行开始摆放
    • 1 如果还有没放的位置,把皇后放到这个位置上
    • 2 查看是否和之前摆放的皇后冲突,如果冲突到3,否则到4
    • 3 结束
    • 4 如果还有皇后,对这个皇后重复1,如果没有皇后对上一个皇后重复1

代码

using System;
namespace DataStructure
{
  /*
  计算8皇后问题有多少不同的解

  问题:
  如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后
  任两个皇后都不能处于同一条横行、纵行或斜线上
   */
  public class Queens8
  {
    /*
    用来放置皇后
    值j在数组中的位置i表明第i个皇后放在第j列上
     */
    int[] array = new int[9];
    public int[] sums = new int[9];

    /*
    判断当前摆法是否合理
    不在同一行:因为摆放的时候 array[index] = j 保证每个皇后都不在同一行
    不在同一列:array 中没有相同的值
    不在对角线:(r1,c1), (r2,c2) 一个位置(r,c),当两个位置|r-r2| == |c-c2|的值相同则在对角线
     */
    public bool Pass(int n)
    {
      if (n == 1)
      {
        return true;
      }
      /*
      某一列和它后面所有的列比较
      某一个位置和它后面所有的位置比较
       */
      for (var r = 1; r <= n; r++)
      {
        for (var r2 = r + 1; r2 <= n; r2++)
        {
          //列相同
          if (array[r] == array[r2])
          {
            return false;
          }
          //任意2个位置对角线
          if (Math.Abs(r - r2) == Math.Abs(array[r] - array[r2]))
          {
            return false;
          }
        }
      }

      return true;
    }

    public int Calculate(int pos)
    {
      if (pos > 8)
      {
        return 1;
      }
      else
      {
        var sum = 0;
        for (var j = 1; j <= 8; j++)
        {
          array[pos] = j;
          if (Pass(pos))
          {
            sum += Calculate(pos + 1);
          }
        }
        sums[pos] = sum;
        return sum;
      }
    }

    public static void TestQueens8()
    {
      var q8 = new Queens8();
      var r = q8.Calculate(1);
      var sums = q8.sums;
      BaseSolution.println(r);
      BaseSolution.printArray(sums);
    }
  }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值