用C#解决八皇后问题
一.引言
首先,我们先了解一下什么是八皇后问题:
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
我们可以思考一下n皇后问题,当然,这里的n需要满足条件n=1或n≥4。
二.工具
已配置好C#实验环境的Visual Studio 2017
三.具体过程
-
分析
如果是我们人为地来解决八皇后问题,我们会怎么想呢?大多数人肯定是在第一行第一列的位置放一个皇后,然后移到第二行,从第一列开始判断,发现第一列不可以,移到第二列,也是不可以,然后移到第三列,诶,第三列可以,那放置一个皇后,移到第三行,继续…当我们发现某一行没找到放皇后的位置,那肯定会回到上一行,将上一行的皇后移到目前位置的下一个位置,再去看看下一行是否能放皇后,如果能,移到下一行继续,如果不能,移到上一行继续。
-
具体代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace eightQueens { class Program { static int count = 0; static void Main(string[] args) { int n = Int32.Parse(Console.ReadLine()); //输入n,选择n皇后问题 List<int> queen = new List<int>(n); //创建一个数组 for (int i = 1; i <= n; i++) //数组初始化 queen.Add(0); PutQueen(n, queen, 0); Console.WriteLine(count); Console.ReadKey(); } private static void PutQueen(int n, List<int> queen, int row) //在某个位置放置皇后 { for (queen[row] = 1; queen[row] <= n; queen[row]++) { if (CheckQueens(queen, row)) { row++; if (row < n) PutQueen(n, queen, row); else { count++; for (int i = 0; i < n; i++) Console.Write(queen[i].ToString() + " "); Console.WriteLine(); } row--; } } } private static bool CheckQueens(List<int> queen, int row) //判断某个位置是否可以放置八皇后 { for (int i = 0; i < row; i++) { if (Math.Abs(queen[i] - queen[row]) == Math.Abs(i - row) || queen[i] == queen[row]) return false; } return true; } } }
-
代码分析
count为解法数。
先创建一个长度为8的数组,数组第一位隐式表示第一行,存储的数字表示第几列。放置的皇后位置信息可以通过数组元素确定,例如queen[2]=6表示皇后放在第二行第六列。
代码中主要用到两个函数–PutQueen和CheckQueens。函数CheckQueens主要判断该位置的皇后与已放置的皇后是否冲突;函数PutQueen主要是放置皇后,从第一行的第一列开始,经函数CheckQueens判断后表明该位置可以放置,然后判断是否还有下一行,如果有则移到下一行的第一列继续判断,如果没有表示已到最后一行,皇后放置结束,输出结果,然后退回到上一行的下一列继续判断。
- 结果截图
八皇后问题一共有92种解法。
四.总结
本篇文章介绍了在C#中用递归法解决皇后问题。思想要点为判断每一个位置是否可以放置皇后。
9/28/2018 4:33:28 PM