算法日记(三)之回溯法解决八皇后问题

回溯法是算法中很常见的一种(在后面的树我们会经常和它打交道)。先简单说一下概念吧(详细的后面讲树再说吧):回溯法从问题本身出发,寻找可能实现的所有情况。和穷举法的思想相近,不同在于穷举法是将所有的情况都列举出来以后再一一筛选,而回溯法在列举过程如果发现当前情况根本不可能存在,就停止后续的所有工作,返回上一步进行新的尝试。

八皇后问题是一个以国际象棋为背景的问题:如何能够在 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种解法):

(中间就省略啦)在此致敬一下高斯先生,听小甲鱼说他把自己最后时光献给这道题(他当时是笔算的,那时没有什么计算机哦)。 

 本贴为博主亲手整理。如有错误,请评论区指出,一起进步。谢谢大家的浏览.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值