回溯法是算法中很常见的一种(在后面的树我们会经常和它打交道)。先简单说一下概念吧(详细的后面讲树再说吧):回溯法从问题本身出发,寻找可能实现的所有情况。和穷举法的思想相近,不同在于穷举法是将所有的情况都列举出来以后再一一筛选,而回溯法在列举过程如果发现当前情况根本不可能存在,就停止后续的所有工作,返回上一步进行新的尝试。
八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后。为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

源代码:
#include <stdio.h>
int Queenes[8] = { 0 }, Counts = 0;
int Check(int line, int list)
{
//遍历该行之前的所有行
for (int index = 0; index < line; index++) //这里就是每一列的数字都是一样的,这样也就不用考虑皇后放置在同一行的情况。
{
//挨个取出前面行中皇后所在位置的列坐标
int data = Queenes[index];//其实就是这个data是0.
//如果在同一列,该位置不能放
if (list == data) {
return 0;
}
//如果当前位置的斜上方有皇后,在一条斜线上,也不行
if ((index + data) == (line + list)) {
return 0;
}
//如果当前位置的斜下方有皇后,在一条斜线上,也不行
if ((index - data) == (line - list)) {
return 0;
}
}
//如果以上情况都不是,当前位置就可以放皇后
return 1;
}
//输出语句
void print()
{
for (int line = 0; line < 8; line++)
{
int list;
for (list = 0; list < Queenes[line]; list++)
printf("0");
printf("#");
for (list = Queenes[line] + 1; list < 8; list++) {
printf("0");
}
printf("\n");
}
printf("================\n");
}
void eight_queen(int line) {
//在数组中为0-7列
for (int list = 0; list < 8; list++) {
//对于固定的行列,检查是否和之前的皇后位置冲突
if (Check(line, list)) {
//不冲突,以行为下标的数组位置记录列数
Queenes[line] = list;
//如果最后一样也不冲突,证明为一个正确的摆法
if (line == 7)//最后一行需要结合判断
{
//统计摆法的Counts加1
Counts++;
//输出这个摆法
print();
//每次成功,都要将数组重归为0
Queenes[line] = 0;
return;
}
//继续判断下一样皇后的摆法,递归
eight_queen(line + 1);//列数加一再进行重复操作,类似递归
//不管成功失败,该位置都要重新归0,以便重复使用。
Queenes[line] = 0;
}
}
}
int main() {
//调用回溯函数,参数0表示从棋盘的第一行开始判断
eight_queen(0);
printf("摆放的方式有%d种", Counts);
return 0;
}
程序执行图(真的有点长,毕竟92种解法):
(中间就省略啦)在此致敬一下高斯先生,听小甲鱼说他把自己最后时光献给这道题(他当时是笔算的,那时没有什么计算机哦)。
本贴为博主亲手整理。如有错误,请评论区指出,一起进步。谢谢大家的浏览.
3849

被折叠的 条评论
为什么被折叠?



