zoukankan      html  css  js  c++  java
  • 递归回溯法解决八皇后问题

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

    具体的算法可以分解为:

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

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

    第一步:

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

    输出如下:

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

  • 相关阅读:
    CLR执行模式之程序集代码的执行
    CLR执行模式之托管代码程序集浅析
    第十章 使用变量的一般事项
    第九章伪代码编程过程 The PseudoCode Programming Process
    第八章防御式编程(代码大全读后)
    第七章实战高质量的子程序(代码大全第七章读后)
    一时看不明白大神的想法
    debain9 debian8 alpine 3.7 aliyun
    elk7
    ansible
  • 原文地址:https://www.cnblogs.com/webor2006/p/3458393.html
Copyright © 2011-2022 走看看