八皇后问题

问题简介

 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。

参考资料: 八皇后问题-百度百科

由问题的条件可知,符合条件的放置方法必然每一行或每一列存在一个皇后。所以将用递归方法,逐行逐点尝试放置皇后棋子。在放置每一行的皇后时,只要考虑到之前行的皇后能不能攻击到目标点。由于运用了递归,可在每一行逐点尝试放置皇后棋子,直到最后成功放置最后一行的皇后。

实现代码:

//输出与统计符合条件的棋盘排列
void PrintCheckerBoard(int checkerBoard[8][8]) {
    static int times = 0;//静态变量用于统计情况个数
    times++;
    printf("第%d种情况:\n", times);
    for (int x = 0; x < 8; x++) {
        printf("---------------------------------\n");
        for (int y = 0; y < 8; y++) {
            if (checkerBoard[x][y] == 1)printf("| * ");
            else printf("|   ");
        }
        printf("|\n");
    }
    printf("---------------------------------\n");
    printf("\n\n");
}

//检查目标点是否符合皇后放置条件(若符合返回0,不符合返回1)
int CheckPoint(int checkerBoard[8][8], int x, int y) {
    //由于是逐层放置,检查目标点所在层前相应位置是否有棋子
    for (int i = 0; i < x; i++) {
        //检查目标点所在列上方是否有棋子
        if (checkerBoard[i][y]) return 1;
    }
    int i = 1;
    while (x - i >= 0 && y - i >= 0) {
        //检查目标点左斜上方是否有棋子
        if (checkerBoard[x - i][y - i])
            return 1;
        i++;
    }
    i = 1;
    while (x - i >= 0 && y + i < 8) {
        //检查目标点右斜上方是否有棋子
        if (checkerBoard[x - i][y + i])
            return 1;
        i++;
    }
    return 0;
}

//问题解决使用的递归函数
void EightQueensProblem(int checkerBoard[8][8], int x) {
    for (int y = 0; y < 8; y++) {//尝试放置当前层的每一个位置
        if (CheckPoint(checkerBoard, x, y))continue;
        //如果该位置不符合要求,则直接进入下一循环
        checkerBoard[x][y] = 1;
        //在当前位置放置皇后棋子
        if (x == 7)PrintCheckerBoard(checkerBoard);
        //如果放置的棋子在最后一层,则输出当前放置情况
        else EightQueensProblem(checkerBoard, x + 1);
        //若不是最后一层,则进行下一层的放置
        checkerBoard[x][y] = 0;
        //移除当前位置的皇后棋子,以进行下一位置的放置

    }
}

//问题实现函数
void Play() {
    int *checkerBoard = (int *)malloc(sizeof(int) * 8 * 8);
    //申请空间作为棋盘的数据结构
    for (int i = 0; i < 64; i++)*(checkerBoard + i) = 0;
    //初始化棋盘
    EightQueensProblem(checkerBoard, 0);
    //调用递归解决问题
    system("pause");
}

void main(void) {
    Play();
    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值