• n皇后问题


    leetcode51. N-Queens

    • 回溯法
    • 本质:深度优先(隐式图搜索)
    • 这里不用二维数组处理起来更简单,一列一列的去看,去递归
    • 决策产生状态,巧妙利用全局标记量记录状态,来剪枝。
    • 斜线的处理方法,是直接看行列的和或差,因为斜线方程是x + y = k 和 x - y = k
    • 递归出来后面的语句记得恢复状态
    • 时间复杂度O(n^n) (暴力法下的状态空间数)
    #include <iostream>
    #include <vector>
    #include <string>
    using namespace std;
    
    class Solution {
    private:
        vector<vector<string> > ans;
        bool row[20];
        int col[20];          //col[i] 的值表示第i列的皇后在该列什么位置(位置也是从0到n)
        bool leftSlash[20];   //左斜线,像中文的捺 
        bool rightSlash[20];  //右斜线,像中文的撇
    /*
    斜线,方程是x + y = k 和 x - y = k 所以去查k的值,就知道这条斜线是否能放皇后,也就是下面代码呈现的
    leftSlash[index + i] 和 rightSlash[index - i + n - 1]
    是因为下标不能为负,所以坐标平移后是 index - i + n - 1
    */
    public:
        vector<vector<string> > solveNQueens(int n) {
            dfs(0, n);
            return ans;
        }
        
        void dfs(int index, int n){  //index表示现在检查的列
            if(index >= n) {  //递归结束条件
                vector<string> rowAns;
                for(int i = 0; i < n; i++){   //存储结果,按行存储
                    string tmp;
                    for(int j = 0; j < n; j++){
                        if(j == col[i])
                            tmp += "Q";
                        else
                            tmp += ".";
                    }
                    rowAns.push_back(tmp);
                }
                ans.push_back(rowAns);
                return;
            }
            // 下面按行去 dfs, 列肯定不会冲突,因为本身涉及了按列参数去递归
            for(int i = 0; i < n; i++){
                //如果该行能放皇后,且不与斜线冲突,那么才进行里面的递归。剪枝
                if(!row[i] && !leftSlash[index + i] && !rightSlash[index - i + n - 1]){
                    col[index] = i;  //让index这列的皇后在i行的位置
                    row[i] = true;
                    leftSlash[index + i] = true;
                    rightSlash[index - i + n - 1] = true;
                    dfs(index + 1, n);
                    //递归出来记得用下面几句恢复状态,这样才能再进行别的 dfs 不出错
                    row[i] = false;  // false 状态表示这个位置没有皇后
                    leftSlash[index + i] = false;
                    rightSlash[index - i + n - 1] = false;
                }
            }
        }
    };
    
    int main(){
    	int n;
    	cin >> n;
    	vector<vector<string> > res;
    	Solution *test = new Solution();
    	res = test->solveNQueens(n);
    	
    	for(int i = 0; i < res.size(); i++){
    		for(int j = 0; j < res[0].size(); j++){
    			cout << res[i][j] << endl;
    		}
    		cout << endl;
    	}
    	
    	cout << res[0].size() << "皇后有" << res.size() << "种摆法" << endl;
    	return 0;
    }
    

    另外,骑士周游(马踏棋盘)问题,可以加上A*启发式优化方法,即改变搜索顺序。

    参考 julyedu 图搜索实战班第一课

  • 相关阅读:
    MQ、JMS以及ActiveMQ 关系的理解
    java对象 深度克隆(不实现Cloneable接口)和浅度克隆
    crontab 各参数详解及如何查看日志记录
    mybatis xml 文件中like模糊查询
    jexl2 执行字符串Java代码
    java代码执行字符串中的逻辑运算方法
    mybatis 传入多个参数
    mybatis通用mapper源码解析(二)
    mybatis通用mapper源码解析(一)
    mybatise插件反向生成数据库表相关Java代码
  • 原文地址:https://www.cnblogs.com/xrszff/p/10961789.html
Copyright © 2020-2023  润新知