输入一个N,找出所有在N行N列的棋盘摆放N个皇后的方法。
递归【例如求八皇后】
直接带入求八皇后
#include <stdio.h>
#include <math.h>
/*八皇后问题是在8*8的棋盘上放置8枚皇后,使得棋盘中每个横向、纵向、左上至右下斜向、右上至左下斜向均只有一枚皇后。
求解出所有摆法,一共有92种摆法*/
const int N = 8; //棋盘行数
int a[N] = {0}; //表示棋盘,若a[2]=2,则表示在第3行第2列放一个皇后,因为同一行不能放两个皇后,所以只需要1维数组就可以表示一个棋盘。
int solution = 0;//解的个数
//row行,col列, 是否可以摆皇后
bool IsOK(int row, int col)
{
for (int i = 0; i < row; i++)
{
if (a[i] == col || (abs(a[i] - col) == row - i))
{
return false;
}
}
return true;
}
void Display()
{
printf("第%d种解:\n",++solution);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (a[i] == j)
{
printf("%d", i);
}
else
{
printf("#");
}
}
printf("\n");
}
printf("-----------------\n");
}
void DSF(int row)
{
for (int col = 0; col < N; col++)
{
//find
if (IsOK(row, col))
{
a[row] = col;
//forward
if (row != N -1)
{
DSF(row + 1);
}
else
{
//done
Display();
}
}
}
//back
}
int main()
{
DSF(0);
return 0;
}
- 结果共92种解法
用n带入求八皇后
#include<stdio.h>
#include<math.h>
int n,count=0;
int a[15]={0};
void dfs(int k)
{
int i,j;
if(k>=n+1)
{
count++;
return ;
}
for(i=1;i<=n;i++)
{
for(j=1;j<k;j++)
{
if(i==a[j]||abs(i-a[j])==abs(k-j))
{
break;
}
}
if(j==k){
a[k]=i;
dfs(k+1);
}
}
return ;
}
int main()
{
int i;
while(scanf("%d",&n)!=EOF&&n!=0)
{
for(i=1;i<=n;i++)
{
a[i]=0;
}
count=0;
dfs(1);
printf("%d\n",count);
}
return 0;
}
结果
非递归【例如五皇后】
#include <stdio.h>
#include <malloc.h>
#include <math.h>
int place(int i, int k, int* p); //检查k+1行i列能否放置皇后,能返回1,否则返回0
int find(int n, int* p, int k, bool n_is_odd); //在k+1行搜索可以放置皇后的位置,找到位置后返回列标,否则返回0
void output(int n, int* p); //输出n皇后问题的一个解
int main()
{
int k, n;
int m;
int* p;
printf("you want to solve n queens problem\n");
printf("n=");
scanf("%d", &n); //输入问题规模
p = (int*)malloc(n * sizeof(int)); //p[k]表示k+1行皇后所在列
for (k = 0; k < n; k++)
{
p[k] = 0; //初始化数组p
}
k = 0; //初始化为第一行
m = 0; //记录解的个数变量初始化
bool n_is_odd = false;
if (n % 2 != 0)
{
n_is_odd = true;
}
int max_col;
if (n_is_odd)
{
max_col = n / 2 + 1;
}
else
{
max_col = n / 2;
}
while (true)
{
if (k == 0) //进入或回溯至第一行
{
p[k] = p[k] + 1; //试探下一列
if (p[k] > max_col) //利用max_col剪枝,如果n为奇数,第一行第n/2+1列试探完毕后终止,否则n/2列试探完毕后终止
{
break;
}
k++; //试探下一行
}
else
{
int temp;
if ((temp = find(n, p, k, n_is_odd)) == 0) //k+1行没有找到可放置皇后的位置
{
p[k] = 0; //必要的清理
k--; //回溯
}
else
{
p[k] = temp; //在k+1行找到的位置赋予p[k]
if (k != (n - 1)) //皇后没有全部放置完毕
{
k++; //试探下一行
}
else //皇后全部放置成功,找到解
{
m++;
printf("The %dnd solution\n", m);
output(n, p); //输出解
}
}
}
}
printf("There are %d solutions in total\n", m); //输出解的个数
return 0;
}
int place(int i, int k, int* p)
{
int m;
for (m = 0; m < k; m++)
{
if ((p[m] == i) || (abs(m - k) == abs(p[m] - i))) //k+1行i列不是合法位置
return (0);
}
return (1); //k+1行i列是合法位置
}
int find(int n, int* p, int k, bool n_is_odd)
{
int i;
i = p[k];
int max_col = n;
if (k == 1) //如果当前行为第二行且n为奇数,同时第一行皇后位置为正中间,则第二行最多试探到n/2列终止
{
if (n_is_odd && p[0] == n / 2 + 1)
{
if (i + 1 < n / 2)
return i + 1;
else
{
return 0;
}
}
}
for (i++; i <= max_col; i++)
{
if (place(i, k, p) == 1) //在k+1行找到可放置皇后的列
return (i); //返回该列
}
return (0); //在k+1行没有找到可放置皇后的列
}
void output(int n, int* p)
{
int i, j;
for (i = 0; i < n; i++)
{
for (j = 1; j <= n; j++)
{
if (j == p[i])
printf("1 ");
else
printf("0 ");
}
printf("\n");
}
printf("\n");
}