递归回溯法解决八皇后问题

继上次学完函数之后,这次来通过一个实例来加深印象,下面会对其实现过程进行一一剖新,先看一下什么叫“八皇后问题”

《递归回溯法解决八皇后问题》

 

具体的算法可以分解为:

《递归回溯法解决八皇后问题》

像上图中第五行就已经出现了死胡同,这时应该退到第四行,重新安放皇后:

《递归回溯法解决八皇后问题》

了解了算法流程,下面一步一步来实现:

第一步:

#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'); }
}

输出如下:

《递归回溯法解决八皇后问题》

好了,今天的练习到此,至于怎么回溯的,需看代码仔细体会下。

    原文作者:八皇后问题
    原文地址: https://www.cnblogs.com/webor2006/p/3458393.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞