问题描述:
一个n*n的棋盘,要在上面放n个皇后。规则:两个皇后之间如果是同列、同行、同对角线它们会互相攻击。也就是说:棋盘上的任意两个皇后皇后
不能为同列、同行、同对角线。
问题分析
对于这个问题、当n不大的时候,可以用穷举法实现。对于n皇后,每一行有n个位置可以放,一共n行。就会有n的n次方种情况。对于这些情况、再一一判断是不是满足情况。
其实一个关键的点在于:什么时候判断已经放了皇后的棋盘是否满足条件,大致可以分为两种:
1、等棋盘上放了n个皇后以后判断
2、放一个皇后判断一次、对于特定的某一次,如果这种情况不满足条件,那么以这种情况为基础而生成的情况就不用再判断了,他们都不会满足条件。
比如说:头两行有冲突,那么后面的不管怎么放,都没有意义了,总会有冲突。
如下图:
这时候我们就可以清楚看到,如果采用穷举法则问题规模是Q(n!),然后对这些可能情况,去掉对角线的情况.(因为行冲突,列冲突已经排除了).
但是如果我们放一个皇后判断一次,则有些情况就不必继续往下判断.
从上图就可清晰地看明白,递归就是一个多叉树的深度优先遍历.
结果如下:(采用了两种方案,递归和非递归的回溯法)
代码如下:
#include<stdio.h>
#include<math.h>
#define N 4
#define true 1
#define false 0
#define INITIAL -1
typedef int bool;
int queen[N];
int count_recursive = 0;
void init_queen()
{
int i;
for(i = 0; i < N; i++)
{
queen[i] = INITIAL;
}
}
void print_queen()
{
int i, j;
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
if(queen[i] == j)
printf(" * ");
else
printf(" 0 ");
}
printf("\n");
}
printf("\n\n");
}
void place_queen(int row, int col)
{
queen[row] = col;
}
bool valid(int row, int col)
{
int i;
for(i = 0; i < row; i++)
{
// in the same column
if(queen[i] == col)
return false;
// in the same diagonal
if(abs(row - i) == abs(col - queen[i]))
return false;
}
return true;
}
int find_queen()
{
int count = 0;
int row = 0;
int col = 0;
while(row < N)
{
while(col < N)
{
if(valid(row, col))
{
place_queen(row, col);
if(row == N-1)
{
count ++;
printf("the %dst queen.\n", count);
print_queen();
col = queen[row];
col++;
queen[row] = INITIAL;
}
else
{
col = 0; //goto tne next row
break;
}
}
else
{
col ++;
}
}
if(col == N)
{
// backtrace
row--;
if(row < 0) // find all the solutions
return 0;
else
{
col = queen[row];
col++;
queen[row] = INITIAL;
continue;
}
}
row++;
}
}
int find_queen_recursive(int row, int col)
{
int i;
if(row > col)
{
count_recursive++;
printf("the %dst queen.\n", count_recursive);
print_queen();
}
else
{
for(i = 0; i < N; i++)
{
if(valid(row, i))
{
place_queen(row, i);
find_queen_recursive(row + 1, col);
}
}
}
}
int main()
{
printf("not-recursive method:\n");
init_queen();
find_queen();
printf("recursive method:\n");
init_queen();
find_queen_recursive(0, N - 1);
return 0;
}
参考资料:http://www.cnblogs.com/yanlingyin/archive/2011/12/19/2292041.html