这就是传说中超难的N皇后?——详细图解!

这篇具有很好参考价值的文章主要介绍了这就是传说中超难的N皇后?——详细图解!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

✔️本文主题:回溯算法之N皇后 算法
✔️题目链接:N皇后

一、前言

大家好久不见,今天我们一起来学习一道很经典、也很有难度的一道题目——N皇后

二、题目信息

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间 不能 相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。


说白了,这道题题目就是让所有皇后之间不在同一行、同一列、同一对角线,求出所有满足此要求的棋盘!

n皇后问题图解,进击的算法,算法,leetcode,职场和发展,c++,深度优先

如图示,左边3X3的样例就是不符合要求的!!!我们要收集 所有 像4X4这样的样例!!!

三、解题思路

思路分析

一看到这道题目,我们会很自然想要用暴力算法来解决,例如设置一个for循环来遍历第一行、再来一个for循环遍历第二行…依此类推。

暴力算法当然是可以解决这道题目的,但这里就会有一个问题,3X3的棋盘我们套3个循环,那4X4的棋盘呢?5X5的又怎么办呢?

因此我们用暴力循环其实是不太适合这道题目的,因为我们没法控制每次套几个循环,那有没有一种方式能够让我们控制有几个for循环呢?

答案是有的!!!看过上次讲解的小伙伴应该知道,回溯算法恰好是用来实现多重for循环的一个算法,他本质上也是一个暴力算法,回溯算法基础 。


我们按照暴力算法的思路先来分析一下:

核心思路就是:定住第一行的一个元素,然后去下一行定住一个元素,再去下一行定住一个元素,直到底行。

画图表示:
n皇后问题图解,进击的算法,算法,leetcode,职场和发展,c++,深度优先

因为图片大小原因,我只把中间过程的某一步完全画了出来,大家明白暴力算法的思路即可。


那么怎么实现我们这个 可变for循环 呢,是的,就是使用 回溯算法

之前说过,回溯算法本质也是暴力算法,他通过递归的方式来实现多重for循环,从而解决暴力算法无法设计多重循环的问题,那按照回溯算法的基本思路,我们一起来设计一下!!

✔️递归终止条件

什么时候棋盘放下了所有皇后,什么时候就停止递归,啥时候所有皇后都放下了?当然是最后一层for循环也走完了的时候。

这里我再简单补充一句:为什么是for循环走完才证明皇后全都放下了?之前放完皇后不行吗

不要忘记规则的约束,同一行或同一列或同一斜线上的皇后会相互攻击,如果你把两个皇后放到同一行,直接就不符合规则了,因此一行放且必须放一个!!!

✔️每一层的处理逻辑

如果不在最终层,我们就要用递归的思路去实现多重for循环!

for(int i=0;i<n;i++)
{
	chessboard[row][rol] = 'Q'; //确定好这一层的一个皇后
	backtracking();//递归此函数,继续向下执行相同逻辑
	chessboard[row][rol] = '.'; //将刚刚确定好的皇后剔除,换成下一个
	
}

固定好一个元素,要去递归执行下一层了,当满足收集结果的条件后,递归结束,再将棋盘上的皇后剔除,固定下一个元素继续执行相同的逻辑。

能够跳回原来的状态,这就是回溯算法的精髓。

✔️收集结果

当我们进入最终层,就要准备收集结果了,并非所有棋盘都需要收集,我们只需要收集 满足 皇后同一行或同一列或同一斜线上 的棋盘,因此我们需要判断棋盘是否符合要求!

但要把所有情况都算出再来检查就会产生大量时间浪费和代码冗余,因此我们采用放皇后时,就检查棋盘是否符合要求,如果不符合,直接进行下一次循环!

要检查当前位置可不可以放置皇后,需要满足三个条件
n皇后问题图解,进击的算法,算法,leetcode,职场和发展,c++,深度优先

针对以上三种情况,我们写一个简单函数:
n皇后问题图解,进击的算法,算法,leetcode,职场和发展,c++,深度优先

bool CheckBoard(vector<string>& chessboard,int row,int col,int n)
{
	//此函数判断第row行第rol列能不能放皇后

	//同一列
	for (int i = 0;i<row;i++)
	{
		if (chessboard[i][col] == 'Q')
		{
			return false;
		}
	}

	//45°
	for (int i = row - 1, j = col + 1; i >= 0 && j < n ;i--,j++)
	{
		if (chessboard[i][j] == 'Q')
		{
			return false;
		}
	}

	//135°
	for (int i = row-1,j = col-1;i>=0 && j>=0;i--,j--)
	{
		if (chessboard[i][j] == 'Q')
		{
			return false;
		}
	}

	return true;

}

四、参考代码

class Solution {
public:
    vector<vector<string>> result;
    void backtracking(int n, int row, vector<string>& chessboard) 
    {
        if (row == n) 
        {
            result.push_back(chessboard);
            //收集合法的结果,只有合法才能来到最后!!!
            return;
        }
        for (int col = 0; col < n; col++) //行固定了,列开始回溯!!
        {
            if (CheckBoard(chessboard,row, col, n)) 
            { 
                // 验证合法就可以放
                chessboard[row][col] = 'Q'; // 放置
                backtracking(n, row + 1, chessboard);//去遍历下一层!!
                chessboard[row][col] = '.'; // 撤销
            }
        }
    }
    bool CheckBoard(vector<string>& chessboard,int row,int col,int n)
    {
        //此函数判断第row行第rol列能不能放皇后

        //同一列
        for (int i = 0;i<row;i++)
        {
            if (chessboard[i][col] == 'Q')
            {
                return false;
            }
        }

        //45°
        for (int i = row - 1, j = col + 1; i >= 0 && j < n ;i--,j++)
        {
            if (chessboard[i][j] == 'Q')
            {
                return false;
            }
        }

        //135°
        for (int i = row-1,j = col-1;i>=0 && j>=0;i--,j--)
        {
            if (chessboard[i][j] == 'Q')
            {
                return false;
            }
        }

        return true;
    }
    vector<vector<string>> solveNQueens(int n) 
    {
        vector<string> chessboard(n, string(n, '.'));
        backtracking(n, 0, chessboard);
        return result;
    }
};

五、结语

回溯算法是一种很神奇的算法,他能通过递归来实现多重for循环,从而将复杂的问题解除,虽然本质上他还是暴力算法,但对于全排列、N皇后这类问题,能解出答案就已经很不错了~

如果你感觉有所收获,可以点赞 + 收藏 +关注 支持一下蓝色学者哦~ 我们下次见~文章来源地址https://www.toymoban.com/news/detail-787508.html

到了这里,关于这就是传说中超难的N皇后?——详细图解!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • DFS(深度优先遍历、N皇后问题、2N皇后问题)

    目录 一、回溯法与深度优先搜索(DFS) 二、DFS与二叉树的前序遍历 2.1、二叉树的前序遍历 2.2、DFS 全排列  2.3、分析 三、N皇后问题 1. 回溯法: 是一种通过探索所有可能的候选解来找出所有解的算法。如果候选解被确认不是一个解的话(或者至少不是最后一个解),回溯法

    2024年03月21日
    浏览(55)
  • 【LeetCode力扣】LCR170 使用归并排序的思想解决逆序对问题(详细图解)

    目录 1、题目介绍 2、解题思路 2.1、暴力破解法 2.2、归并排序思想 2.2.1、画图详细讲解 2.2.2、归并排序解决逆序对的代码实现 首先阅读题目可以得出要点,即当 前数 大于 后数 时则当作一个【逆序对】,而题目是要求在一个数组中计算一共存在多少个这样的逆序对并输出结

    2024年02月08日
    浏览(45)
  • 回溯法求解八皇后问题

    问题提出 :八皇后问题是一个古老而著名的问题。该问题是十九世纪著名的数学家高斯1850 提出在 8x8 格的国际象棋上摆放八皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志

    2023年04月08日
    浏览(57)
  • 四皇后问题(多种方法)

    问题描述 : 以4皇后为例,其他的N皇后问题以此类推。所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子。在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平、竖直、以及45度斜线上都不能出现皇后的棋子。 回溯法 : dfs

    2024年02月04日
    浏览(26)
  • Python 解决八皇后问题

       八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的 n 皇后摆放问题:这时棋

    2024年02月06日
    浏览(50)
  • Java实现八皇后问题

    八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于 1848 年提出:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 第一个皇后先

    2024年02月14日
    浏览(30)
  • python解决8皇后问题

    row_str = ‘.’ * col + ‘Q’ + ‘.’ * (n - col - 1) 这行代码用于构建一个字符串,表示当前行的皇

    2024年02月13日
    浏览(33)
  • [C++实现]八皇后问题

    一、题意解析 国际象棋中的皇后,可以横向、纵向、斜向移动。如何在一个8X8的棋盘上放置8个皇后,使得 任意两个皇后都不在同一条横线、竖线、斜线方向上 ?八皇后问题是一个古老的问题,于1848年由一位国际象棋棋手提出:在8×8格的国际象棋上摆放八个皇后,使其不能

    2024年02月06日
    浏览(29)
  • 回溯法--n皇后问题

    回溯法有两个模板--子集树、排列树,他们有回溯法的共同特点:深度优先搜索,如果一条路走不通,再退回来(类似递归) 八皇后问题最早是由国际象棋棋手马克斯·贝瑟尔(Max Bezzel)于1848年提出。第一个解在1850年由弗朗兹·诺克(Franz Nauck)给出。并且将其推广为更一般

    2024年02月02日
    浏览(54)
  • 八皇后问题(回溯法)

    目录 什么是八皇后 八皇后问题怎么解决? 什么是回溯法 回溯法的模板 八皇后问题的核心代码 判断皇后位置是否可行 总体实现代码 每日一句: 种一棵树的最好时间是十年前,其次是现在。 八皇后问题(英文:Eight queens),是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出的

    2023年04月09日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包