继上次学完函数之后,这次来通过一个实例来加深印象,下面会对其实现过程进行一一剖新,先看一下什么叫“八皇后问题”
具体的算法可以分解为:
像上图中第五行就已经出现了死胡同,这时应该退到第四行,重新安放皇后:
了解了算法流程,下面一步一步来实现:
第一步:
#include <stdio.h>
#define QUEEN_NUM 8
int queen[QUEEN_NUM];
// 在第y行上放置皇后
void place(int y);
int main(void)
{
place(0);//首先从第1行开始放置
return 0;
}
void place(int y)
{
}
说明一下queen[QUEEN_NUM]数组的含义:
queen[0] = 3代表该皇后y轴的坐标为0,x轴的坐标为3;
queen[1] = 5代表该皇后y轴的坐标为1,x轴的坐标为5;
这样用一个一维数组就可以表达八皇后的问题。
第二步:
#include <stdio.h>
#define QUEEN_NUM 8
int queen[QUEEN_NUM];
// 在第y行上放置皇后
void place(int y);
// 检测在第y行第x列能否放置皇后
int check(int y, int x);
void show();
int main(void)
{
place(0);
return 0;
}
void place(int y)
{
if (y == 8)//直接显示八皇后坐标
{
show();
return;
}
int i;
for (i=0; i<QUEEN_NUM; i++) // 在第y行的每一列上试探
{
if (check(y, i))
{
queen[y] = i;
place(y+1); // 在下一行放置皇后
}
}
}
第三步:实现判断是否坐标点能否放置皇后的方法
#include <stdio.h>
#define QUEEN_NUM 8
int queen[QUEEN_NUM];
// 在第y行上放置皇后
void place(int y);
// 检测在第y行第x列能否放置皇后
int check(int y, int x);
void show();
int main(void)
{
place(0);
return 0;
}
int check(int y, int x)
{
int i;
for (i=0; i<y; i++)
{
if (queen[i] == x || y - i == abs(x - queen[i]))//如果在同一列,或是斜线上的,则不能存放
return 0;
}
return 1;
}
void show()
{
}
void place(int y)
{
if (y == 8)
{
show();
return;
}
int i;
for (i=0; i<QUEEN_NUM; i++) // 在第y行的每一列上试探
{
if (check(y, i))
{
queen[y] = i;
place(y+1); // 在下一行放置皇后
}
}
}
第四步:显示符合八皇后的坐标:
#include <stdio.h>
#define QUEEN_NUM 8
int queen[QUEEN_NUM];
// 在第y行上放置皇后
void place(int y);
// 检测在第y行第x列能否放置皇后
int check(int y, int x);
void show();
int main(void)
{
place(0);
return 0;
}
int check(int y, int x)
{
int i;
for (i=0; i<y; i++)
{
if (queen[i] == x || y - i == abs(x - queen[i]))
return 0;
}
return 1;
}
void show()
{
int i;
static int count = 0;//这个只会初始化一次,所以该函数是有状态的,可以一直累加
printf("the %d solution\n", ++count);
for (i=0; i<QUEEN_NUM; i++)
{
printf("(%d, %d) ", i, queen[i]);
}
putchar('\n');
}
void place(int y)
{
if (y == 8)
{
show();
return;
}
int i;
for (i=0; i<QUEEN_NUM; i++) // 在第y行的每一列上试探
{
if (check(y, i))
{
queen[y] = i;
place(y+1); // 在下一行放置皇后
}
}
}
运行结果:总共92个解
这样打印出来不太直观,实际上可以9空格的样式打印出来:
void show()
{
int i;
int j;
static int count = 0;//这个只会初始化一次,所以该函数是有状态的,可以一直累加
printf("the %d solution\n", ++count);
for (i=0; i<QUEEN_NUM; i++)
{
printf("(%d, %d) ", i, queen[i]);
}
putchar('\n');
for (i=0; i<QUEEN_NUM; i++) // 行
{
for (j=0; j<QUEEN_NUM; j++) // 列
{
if (queen[i] == j)//代表这一个坐标为皇后,就输出Q
printf("Q ");
else
printf("x ");//代表这一个坐标没有皇后,就输出X
}
putchar('\n');
}
}
输出如下:
好了,今天的练习到此,至于怎么回溯的,需看代码仔细体会下。
关注个人公众号,获得实时推送