回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define N_size 7
#define INITIAl -1000
int N=N_size;
int count = 0;
void init(int a[])
{
int *p = a;
for(int i = 0; i<=N_size; i++)
{
*p = INITIAl;
p++;
}
}
void Print(int a[])
{
for(int i = 0; i<=N-1; i++)
{
//printf("第%d行, a[i] is:%d\n",i, a[i]);
for(int j = 0; j<=N-1; j++)
{
if(a[i] == j)
printf(" #");
else
printf(" .");
}
printf("\n");
}
}
bool can_place(int i, int j, int a[])
//判断第i行, 第j列是否可以放置皇后
{
for(int m = 0; m<=N-1; m++)
{
//printf("第 %d 行, 第%d 列, a[m] is: %d.\n", i, j, a[m]);
if((a[m] == j) || (abs(a[m] - j) == abs(m-i)))
return false;
}
return true;
}
void queens(int N, int i, int a[])
{
//往第i行放置皇后:前i-1行已经放好
if(i == N)
//it's time to print the result
{
Print(a);
count++;
}
else
{
for(int j = 0; j<=N-1; j++)
{
if(a[i] == INITIAl) //若a[i]的值为initial, 则说明第i行还没有放置皇后
{
if(can_place(i, j, a))
{
printf("可以往第%d行 第%d列 放置皇后\n",i, j);
a[i] = j; //place at (i,j):第i行, 第j列
queens(N, i+1, a);//继续往第i+1行放置皇后
//如果在第i行第j列放置皇后之后, 能继续探索到第i+1行的皇后放置位置, 并最终找到在第N-1行放置皇后的位置, 则会输出最终结果
//否则, 假设在第i+1行就找不到合适的位置,则queens(N, i+1, a)函数会什么也不输出, 并返回到这里的a[i] = INITIAl
//意味着取消之前的第i行位置, 从下一个j进行判断, 判断第i行第j+1列是否可以放置
a[i] = INITIAl;//这一句实现回溯到上一层
}
}
}
}
}
int main()
{
int a[N_size];
//需要在防止皇后前对a进行初始化, 且每个元素值都是负数, 否则会自动初始化为全0, a[0] = 0,即默认将第0行的皇后放在了第一列
init(a);
queens(N_size, 0, a);
printf("共有%d种解法.", count);
}
a[N_size]用来保存每一行皇后所在列数,a[4]=4代表第四行的皇后放在第4列.