C数组解决八皇后问题

这里写图片描述

引用这首诗为了引出一个算法,叫做回溯法.
什么是回溯,通俗的解释就是当你发现自己当初的选择是错误的时候,用时光机把你送回到做选择的那一天,让你重来一次.想一想如果高考时给你这样的福利,岂不是美滋滋?
一下关于八皇后的解法,就是利用了回溯法.
首先做一个最简单的说明,因为八个皇后互相之间都攻击不到,即不能在同一行,同一列,同一对角线.所以我们每一次只需要确定第一行的皇后的位置就可以.
先在第一行的第一列放置一个皇后,此时它一定是合理的位置.但检测的
步骤不能省.
具体的检测逻辑是,把我们刚刚放置皇后的这一行之前的皇后全部拿过来攻击它,如果攻击不到,就是合法的,我们就继续放下一行.否则,我们就换一列放置,并重新检测.
如果一路检测下来都是合格的,那么第八个皇后放完,我们就得到了第一个解.然后变动上一步的位置继续检测,知道所有的解去不求出.

伪代码更容易理解:

# define _CRT_SECURE_NO_WARNINGS
# include<cstdio>
# include<cstdlib>
# include<cmath>

int 每行中皇后所处的列数[8] = { 0 },合法的摆放方式;  //皇后在每行中所处的列数


void print_map()
{
    printf("\n\n\t\t=================第%d种摆放方法=================", 合法的摆放方式);
    int 行数, 列数;
    for (行数 = 0; 行数 < 8; 行数++)
    {
        printf("\n\t\t\t\t");
        for (列数 = 0; 列数 < 每行中皇后所处的列数[行数]; 列数++)
        {
            printf("□");
        }
        printf("■");
        for (列数 = 每行中皇后所处的列数[行数] +1; 列数 < 8; 列数++)
        {
            printf("□");
        }   
    }

}

//检测当前位置是否合法
int check_positon_valid(int 待检测位置行数, int 待检测位置的列数)
{
    int 已经就位的皇后所处的列数;
    int 已经就位的皇后所处的行数;
    for (已经就位的皇后所处的行数 = 0; 已经就位的皇后所处的行数 < 待检测位置行数; 已经就位的皇后所处的行数++)
    {
        已经就位的皇后所处的列数 = 每行中皇后所处的列数[已经就位的皇后所处的行数];
        if (待检测位置的列数 == 已经就位的皇后所处的列数
            || 待检测位置行数 + 待检测位置的列数 == 已经就位的皇后所处的行数 + 已经就位的皇后所处的列数
            || 待检测位置行数 - 待检测位置的列数 == 已经就位的皇后所处的行数 - 已经就位的皇后所处的列数)
        {
            return 0;
        }
    }
    return 1;
}

void put_queen(int 即将放置的行数)
{
    int 即将放置的列数;
    for (即将放置的列数 = 0; 即将放置的列数 < 8; 即将放置的列数++)
    {
        if (check_positon_valid(即将放置的行数, 即将放置的列数))
        {
            每行中皇后所处的列数[即将放置的行数] = 即将放置的列数;
            if (即将放置的行数 == 7)
            {
                合法的摆放方式++;
                print_map();
                每行中皇后所处的列数[即将放置的行数] = 0;
                return;
            }
            put_queen(即将放置的行数 + 1);
            每行中皇后所处的列数[即将放置的行数] = 0;
        }
    }
}

void main()
{
    put_queen(0);
    printf("一共有%d种合法的摆放方式", 合法的摆放方式);
    getchar();
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值