算法篇----八皇后问题
八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
using System;
using System.Collections.Generic;
namespace NET.MST.Thirteenth.Queen
{
/// <summary>
/// 皇后问题内核模块
/// </summary>
public partial class Queens
{
//棋盘列表,每一项代表一个解的棋盘
private List<int[]> _chessBoard;
//维度
private int _dimension;
/// <summary>
/// 不允许默认的公共构造方法
/// </summary>
private Queens()
{
}
/// <summary>
/// 构造方法,需要提供维度来构造
/// </summary>
/// <param name="n">维度</param>
public Queens(int n)
{
//初始化解
_chessBoard = new List<int[]>(n);
//存储维度
_dimension = n;
//计算并得到所有解
Calculate();
}
/// <summary>
/// 只读属性,返回维度
/// </summary>
public int Dimension
{
get
{
return _dimension;
}
}
public int[] GetChessBoard(int index)
{
if (_chessBoard.Count <= index||
index<0)
return null;
int[] result = new Int32[_dimension];
Array.Copy(_chessBoard[index], result, result.LongLength);
return result;
}
/// <summary>
/// 得到解的数量
/// </summary>
public int GetCount()
{
return _chessBoard.Count;
}
}
/// <summary>
/// 回朔算法的实现
/// </summary>
public partial class Queens
{
/// <summary>
/// 计算入口
/// </summary>
private void Calculate()
{
//初始化一个棋盘
int[] board = new Int32[_dimension];
//循环摆放N个皇后,直至第一皇后也需要回朔
for (int j = 0; j < _dimension && j >= 0; )
{
//是否需要回朔的标志
bool found = false;
//从第一列摆放到第N列
for (int i = board[j]; i < _dimension; i++)
{
//检查是否有冲突
if (NoConflict(j, board, i))
{
//表示没有冲突,实际摆放当前皇后
board[j] = i;
//如何当前摆放的是最后一个皇后,则表明已经找到一个解
if (j == (_dimension - 1))
{
//复制当前棋盘并且存储这个解
int[] result = new Int32[_dimension];
board.CopyTo(result, 0);
_chessBoard.Add(result);
//一个解得到后,就需要回朔来寻找下一个解
found = false;
}
//不需要回朔
else
found = true;
break;
}
}
if (!found)
{
//这里回朔,复位当前皇后
board[j] = 0;
//回朔到上一个皇后
j = j - 1;
if (j >= 0)
board[j]++;
}
else
j++;
}
}
/// <summary>
/// 检查当前摆放是否有冲突
/// </summary>
/// <param name="index">现在摆放第几个皇后</param>
/// <param name="board">当前棋盘</param>
/// <param name="val">当前尝试摆放的列数</param>
/// <returns></returns>
private bool NoConflict(int index, int[] board, int val)
{
//循环检查当前摆放是否和已经摆放的皇后有冲突
//由于是逐行摆放的,所以不存在两个皇后在同一行的可能,只检查列和斜线
for (int i = 0; i < index; i++)
{
if (board[i] == val || //在同一列上
(index - i) == Math.Abs(board[i] - val))//在同一斜线上
return false;
}
//检查接触,无冲突
return true;
}
}
}
广积粮,筑高墙,缓称王