回溯算法应用

173 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。 ​

介绍

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。这个问题要求把n个皇后放在一个nxn的棋盘上,使得任何两个皇后都不能相互攻击,即它们不能同行,不能同列,也不能位于同一条对角线上。对于n=1,问题的解很简单,而且很容易看出对于n=2和n = 3来说,这个问题是无解的。所以我们考虑4皇后问题,并用回溯法对它求解。因为每个皇后都必须分别占据一行,我们需要做的不过是为棋盘上的每个皇后分配一列。

image.png

分析

先从简单的看起,首先,三皇后本来就没有解,先考虑四皇后问题

image.png

我们从空棋盘开始,然后把皇后1放到它所在行的第一个可能位置上,也就是第一行第一列。对于皇后2,在经过第一列和第二列的失败尝试之后,我们把它放在第一个可能的位置,就是格子(2,3),位于第二行第三列的格子。这被证明是一个死胡同,因为皇后将没有位置可放。所以,该算法进行回溯,把皇后2放在下一个可能位置(2,4)上。这样皇后3就可以放在(3,2),这被证明是另一个死胡同。该算法然后就回溯到底,把皇后1移到(1,2)。接着皇后2到(2,4),皇后3到(3,1),而皇后4到(4,3),这就是该问题的一个解。图12.2给出了这个查找的状态空间树。

代码思路

一行一行地摆放,在确定一行中的那个皇后应该摆在哪一列时,需要当前列是否合法,如果合法,则将皇后放置在当前位置,并进行递归,回溯。每行都摆满皇后时,则产生了一种解法,将所有解法收集并返回。 判断合法:当前将要摆放’Q’的位置和其他已摆放‘Q’的位置不能在同一列,且不能在同一条45度斜线或135度斜线上。这里判断是否在同一条斜线上可通过当前将要摆放’Q’的位置和其他已摆放‘Q’的位置横坐标之差和纵坐标之差的绝对值是否相等来判断。


        for (int col = 0;col < n; ++col) {
            if (isValid (row, col, n, chessboard)) {
                chessboard[row][col] = 'Q';
                backTrack(n, row+1, chessboard);
                chessboard[row][col] = '.';
            }
        }