zoukankan      html  css  js  c++  java
  • 经典算法-八皇后

    1 八皇后

    八皇后的问题是:

    一个8X8的棋盘上,摆上8个皇后,皇后的攻击方式是,斜着,横着,竖着。要求摆的8个皇后不能够相互攻击到。

    2 分析

    八皇后的解法是回溯算法。

    而关键问题就在于:判断某个点是否可以摆。

    3 解法

    3.1 使用二维数组备忘

    使用二维数组做备忘,直观很多。按部就班的判断是否可以防止就行了。

    #include <vector>
    #include <iostream>
    
    using namespace std;
    
    bool aux_judge(int row, int col, vector<vector<int>> &memo)
    {
        // 只用到row 的原因在于,后面的都没摆,因此可以不用判断
        // 判断同一列
        for (int i = 0; i < row; ++i)
        {
            if (memo[i][col] == 1)
            {
                return false;
            }
        }
    
        // 判断右斜,因此是row和col都要减少相同的
        for (int i = 1; col - i >= 0 && row - i >= 0 ; ++i)
        {
            if (memo[row - i][col - i] == 1)
            {
                return false;
            }
        }
        // 判断左斜,因此row是在减,col是在加
        for(int i=1;col+i<8&&row-i>=0;++i)
        {
            if(memo[row-i][col+i]==1)
            {
                return false;
            }
        }
        return true;
    }
    
    // row 开始摆第row-1行,ret为解的个数
    void aux(int row, vector<vector<int>> &memo, int &ret)
    {
        // 当row==8 的时候,也就是说前面0~7行,这8行都摆了,那么已经完成了一个解
        if (row == 8)
        {
            ret++;
            return;
        }
    
        // 这一行的 8 个位置依次试一下
        for (int i = 0; i < 8; ++i)
        {
            // 判断 row,i 这个点是否可以摆
            if (aux_judge(row, i, memo))
            {
                memo[row][i] = 1;
                aux(row + 1, memo, ret);
                memo[row][i] = 0; // 回溯
            }
        }
    }
    
    int eight()
    {
        // 使用一个二维数组,记录已经摆的点。可以用bool的。
        vector<vector<int>> memo(8, vector<int>(8, 0));
        int ret = 0;
        aux(0, memo, ret);
        return ret;
    }
    

      

    3.2 使用一位数组备忘

    使用一个8长度的一维数组备忘,数组的低i位,表示第i行,皇后放在arr[i]位置上。

    其中判断是否可以方式的时候,是初中数学时候的知识,也就是 x+y=c1,和y-x=c2.

    bool aux_check(int row, int col, vector<int> &memo)
    {
        for (int i = 0; i < row; ++i)
        {
            // 判断是否有皇后在
            if (memo[i] == col)
            {
                return false;
            }
    
            // memo[i] + i == row + col 的含义是:
            // 当2个点的横纵坐标相加和相等的时候,就类似于 x+y =n ,那么两点在同一纸箱上
            // 同理 memo[i] -i== col -row 表示
            // 当两个点的横纵坐标差相等时,类似于 x-y =c ,那么两点也在同一直线上。
            if (memo[i] + i == row + col || memo[i] -i== col -row)
            {
                return false;
            }
        }
        return true;
    }
    
    void aux(int row, vector<int> &memo, int &ret)
    {
        if (row == 8)
        {
            ret++;
            return;
        }
    
        for (int i = 0; i < 8; ++i)
        {
            if (aux_check(row, i, memo))
            {
                memo[row] = i;
                aux(row + 1, memo, ret);
                // memo[row] = 0;  // 这句话是可以省略的,
                // 原因在于,在 aux_check() 判断的时候并不会用到这一行。
            }
        }
    }
    
    int eight()
    {
        // memo 记录的是第 i 行上的皇后位于 memo[i]列
        vector<int> memo(8);
        int ret = 0;
        aux(0, memo, ret);
        return ret;
    }
    

      

    3.2 位运算记录

    位运算太渣。看不懂啊。。。。

  • 相关阅读:
    Who Gets the Most Candies? POJ
    Chrome DevTools谷歌浏览器开发者工具评估资源加载时间
    Array.isArray (Array) – JavaScript 中文开发手册
    CSS3 @keyframes 规则
    inherit (Values & Units) – CSS 中文开发手册
    CSS #id 选择器
    isgraph (Strings) – C 中文开发手册
    PHP juliantojd() 函数
    Navigator javaEnabled() 方法
    ionic checkbox
  • 原文地址:https://www.cnblogs.com/perfy576/p/8568437.html
Copyright © 2011-2022 走看看