zoukankan      html  css  js  c++  java
  • 回溯法:八皇后问题

    什么是回溯法?

    回溯来源于基本的枚举:

    void print(序列A, 集合S)
    {
        if (S为空) 输出序列A
        else 按照“从小到大的顺序”依次考虑S中的每个元素
        {
            print(A的新序列, S-{v}); //递归
        }           
    }

    其中,测试元素通过一个for循环加入,递归通过cur下标指示当前位置。很明显,这是一个对解答树的先序遍历过程,叶节点就是问题的解。

    但是,当问题规模扩大时枚举量指数级的扩大。问题在于枚举将解的判断置于叶节点,而忽视了搜索路径中的判断。因此回溯就应运而生,也就是在测试节点加入时就测试合理性,(合理) ? 递归:剪枝。对于不同的问题,递归框架明确,最重要的是确定判决条件。

    八皇后问题:皇后不同行、同列、同对角线。对角线相当于y=x+c和y=-x+c这两组平行线。程序:

    #include <stdio.h>
    
    int maze[8]; //保存各行选择的列
    int cnt = 0; //解的个数
    
    void dfs(int row)
    {
        if (row == 8)
        { //递归结束条件
            cnt++;
            for (int i = 0; i < 8; i++)
                printf("%d ", maze[i]);
            printf("
    ");
        }
        else
        {
            for (int i = 0; i < 8; i++)
            {//遍历cur行上的所有可能解
                int ok = 1;
                for (int j = 0; j < row; j++)
                {//判断与先前的节点时候冲突
                    if (maze[j] == i || (j - maze[j]) == (row - i) || (j + maze[j]) == (row + i))
                    {//同列 同对角线
                        ok = 0;
                        break;
                    }
                }
    
                if (ok)
                {//不冲突则加入,继续执行递归
                    maze[row] = i;
                    dfs(row + 1);
                }//否则剪枝,测试下一个可能解
            }
        }
    }
    
    int main()
    {
        dfs(0);
        printf("cnt = %d
    ", cnt);
        return 0;    
    }

    最后共有92个解。但是事实上只有12个独立解,如何进行进一步优化是更深入的问题。本文旨在学习回溯的基本框架

     
  • 相关阅读:
    TF-IDF
    智力题
    max{X,Y}和min{X,Y}的概率分布
    K-Means
    提高工作效率:给设计师的10条建议
    每个软件工程师都应该尝试的5件事
    CSS sprite 圆角——源代码
    比较大气的网页元素
    彩色网页变黑白色CSS代码变黑白色调!
    jquery适用技巧
  • 原文地址:https://www.cnblogs.com/zjgtan/p/3140023.html
Copyright © 2011-2022 走看看