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


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

    具体的算法可以分解为:

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

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

    第一步:

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

    输出如下:

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

  • 相关阅读:
    HDU 2844 Coins(多重背包)
    HDU 4540 威威猫系列故事——打地鼠(DP)
    Codeforces Round #236 (Div. 2)
    FZU 2140 Forever 0.5
    HDU 1171 Big Event in HDU(DP)
    HDU 1160 FatMouse's Speed(DP)
    ZOJ 3490 String Successor
    ZOJ 3609 Modular Inverse
    ZOJ 3603 Draw Something Cheat
    ZOJ 3705 Applications
  • 原文地址:https://www.cnblogs.com/webor2006/p/3458393.html
Copyright © 2020-2023  润新知