本文地址:http://blog.csdn.net/spch2008/article/details/9152713
为求简单起见,先看四皇后问题。
所谓皇后问题,即任意两个皇后不能处于同一列,也不能同时处于同一行,而且还不能处于同一对角线上。
我们以列为单位进行放置,即同一列仅放置一个皇后,
1. 假设将皇后放于第一行第一列,则同一行,同一列,对角线上,均不能放置皇后
首先检测对角线,将污染位置用红X表示。
接下来将同一行的污染位置标记为红X
2. 放置第二个皇后
先检测主对角线,将污染位置做标记。
接下来检测辅对角线,标记污染位置。
3. 第三个皇后无法放置,所以必须回溯,重新放置第二个皇后,但同样无法的解。
所以回退到第一步,重新放置第一个皇后的位置。
先检测主对角线
然后是辅对角线
然后是同一行,并放置第二个皇后
主,辅对角线
同一行,并放置皇后
主,辅对角线,同一行,并放皇后
上图即得到一个解。
用一个四原数组记录所得解,数组中每个元素对应棋盘的一列。
例如,上述解可以表示为[2, 4, 1, 3],即第一个皇后放在
第1列第2行,第二个皇后放在第2列第4行,第三个皇后放在
第3列第1行,第四个皇后放在第4列第3行。
我们用result来命名这个数组,
首先有一个检测函数,检测是否可以放置。原理:检测同一行是否有皇后,并检测主辅对角线上是否有皇后,
主辅对角线可根据斜率正负1来判断。
bool place(int *result, int row)
{
for(int i = 1; i < row; i++)
{
if(result[i] == result[row] || abs(i-row) == abs(result[i] - result[row]) )
return false;
}
return true;
}
参数row为正在处理的列,而result[row]为该皇后放置的行。检测该皇后是否与已放置的皇后处于同一行,同时通过斜率检测对角线是否有皇后。
int queen(int n)
{
//抛弃下标为0的元素,从1开始
int *result = new int[n+1];
int row = 1;
int total = 0;
//result初始化
for(int i = 1; i <=n; i++)
result[i] = 0;
while(row >= 1)
{
//首先放置在第一行
result[row] += 1;
//检测该位置是否可以放置,如果不可,放到下一位置,即下一行
while(result[row] <= n && !place(result, row) )
result[row] += 1;
//找到一个解
if(result[row] <= n && row == n)
{
total++;
}
//放置下一皇后
else if(result[row] <= n && row < n)
{
row++;
}
//放置失败,回退到上一皇后,重新放置
else
{
//由于没有放置成功,所以需要置0
result[row] = 0;
//回退到上一个皇后处
row--;
}
}
return total;
}
main函数及结果。
int _tmain(int argc, _TCHAR* argv[])
{
for(int i = 1; i <= 10; i++)
cout << i << "皇后" << queen(i) << endl;
system("pause");
return 0;
}
同样,皇后问题也可以通过递归来解决。
bool place(int *result, int row)
{
for(int i = 1; i < row; i++)
{
if(result[i] == result[row] || abs(i-row) == abs(result[i] - result[row]) )
return false;
}
return true;
}
void recursion(int *result, int row, int N, int &total)
{
if(row > N)
total++;
else
{
for(int line = 1; line <= N; line++)
{
result[row] = line;
if( place(result, row) == true)
recursion(result, row+1, N, total);
}
}
}
int queen(int N)
{
int *arr = new int[N+1];
for(int i = 1; i <= N; i++)
arr[i] = 0;
int total = 0;
recursion(arr, 1, N, total);
return total;
}