以leetcode51题为例
题目分析:
下过国际象棋的都知道,皇后可以在它所在的行,所在的列,还有所在的斜线进行移动
这道题就是给n个皇后,nxn的棋盘,让这n个皇后不能互相吃彼此
算法原理分析:
一、在画决策树之前,我们要想明白,什么样的皇后位置为合法的
1.首先它能够一行和一列,所以我们是每一行一个皇后,每一列一个皇后
2.对角线只能有一个皇后
二、基于以上的理解,我们就可以自己尝试画一下决策树(以下以N=3画)
就是想明白怎么剪枝就行,难点就在这里
dfs函数:你告诉dfs一个行数,dfs就尝试是否能在这一行放皇后,如果能放就放,然后考虑下一层
递归出口:当行数越界的时候收集结果
这里要重点考虑剪枝,如何剪枝???
无非就是想,考虑这个位置能不能放上皇后
1.无脑方法:四次循环,第一次循环寻找这一行有没有皇后,第二次寻找这一列有没有皇后
第三次寻找主对角线有没有皇后,第四次寻找副对角线有没有皇后
但是每个位置都进行四次循环时间复杂度很高(可以小优化,不要循环行,因为我们
是一行一行的枚举的,当回溯到一行的时候,一行的每个位置都是合法的 )
2.类似哈希表的策略:三个数组表示,列/对角线有没有皇后
bool col[n]:当第0行有皇后时,我们可以col[0]=true;
行就不要表示了,因为我枚举行的时候都是合法的
那对角线怎么表示呢???这需要联想高中数学知识,坐标即可
主对角线:y=x+b -> y-x=b 此时发现纵坐标-横坐标为定值
那我们可以bool dig1[2xn]:当y-x=b,把b对应的设为true,dig1[b]=true
但是此时我们又发现一个问题?y-x可能是负数,那dig1就可以越界
可以加上一个偏移量,x最大为n,y最小为0,y-x+n=b+n即可
同理,副对角线也可以这样表示
代码编写: