问题描述:n皇后问题:在N行N列的棋盘上放置不能互相攻击的N个皇后。根据国际象棋规则,处在同一行或同一列或同一斜线上的皇后可以互相攻击。N皇后问题的解满足以下条件:棋盘每行均放置一个皇后,且任何2个皇后不在同一列,也不在同一斜线上。
一般首先想到用二维数组进行求解,但因为皇后不能出现在同一行,所以本题,使用一维数组求解。回溯也需运用递归,深度搜索思想。满足条件就进行下一步,直到完成一种解法,或不满足条件,跳转到回溯点,进行下一步,以此类推。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define n 4//皇后个数
int a[n];//皇后不能在同一行,所以简化为用一维数组存储皇后所在列
int sum = 0;//计算满足条件数
int b[n][n];//存储每种方法
//检查放置位置是否满足条件,皇后不能出现在同一列,同一行,及对角线(斜率为正负1的斜线)
bool Check(int c, int r)
{
for (int i = 0; i < c; i++)
{
if (r == a[i] || abs(c - i) == abs(r - a[i]))//此解法已经排除同一行的情况,所以只用判断是否同一列,和斜线,斜线借助abs()绝对值来处理
return false;
}
return true;
}
void Queen(int k)
{
if (k == n)//放置完成
{
sum++;//计数加一
//这一段是为了输出放置矩阵
printf("放置方法:\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
printf("%d", b[i][j]);
printf("\n");
}
printf("\n");
//
return;
}
for (int i = 0; i < n; i++)
{
if (Check(k, i))
{
//k表示放置皇后的行数,i表示该行皇后放置的列数,即第k行的皇后放置在第i列
a[k] = i;
b[k][i] = 1;//放置后,在矩阵中置1
Queen(k + 1);
b[k][i] = 0;//若无法放置完成,返回回溯点,则把当前位置置0,开始下一位置放置
}
}
}
int main()
{
memset(b, 0, sizeof(b));//该方法是初始化数组
Queen(0);
printf("%d皇后问题的放置方法共有:%d种\n", n,sum);
system("PAUSE");
return 0;
}
示例输入输出:
学习中,欢迎交流