图论 - 图的遍历 - 深度优先搜索 - n皇后问题
Posted fyqq0403
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论 - 图的遍历 - 深度优先搜索 - n皇后问题相关的知识,希望对你有一定的参考价值。
n皇后问题
描述
n皇后问题:一个n×n的棋盘,在棋盘上摆n个皇后,满足任意两个皇后不能在同一行、同一列或同一斜线上的方案有多少种?
输入
第一行包含一个整数n。
输出
输出一个整数,表示方案数。
样例输入
4
样例输出
2
限制
一共10个测试点, 第i个测试点的n=i+4。
时间:2 sec
空间:512 MB
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
C++代码
#include <iostream> using namespace std; int ans, allOne; // ans:答案;allOne:用于二进制&的全1数。 /* 深度优先搜索(用二进制优化)获得合法的皇后摆放位置。 pos:其二进制上的某个位置的1表示当前所在行的相应的位置(列)已经放了一个皇后。 left:其二进制上的某个位置的1表示当前所在行的相应的位置(是由于右对角线上已有皇后)不能放置皇后。 right:其二进制上的某个位置的1表示当前所在行的相应位置(是由于左对角线上已有皇后)不能放置皇后。 */ void dfs(int pos, int left, int right) { /* 当且仅当每一列都放了一个皇后那么整个棋盘已经放了n个合法皇后,故要终止 */ if ( pos == allOne ) { ++ans; // 到了此步,证明已经得到了一个合法的方案。 return; } /* can_put为1的位表示能放皇后。用掩码保证can_put除了低n位以外的更高位均为0,因为取反和下面循环中的左移可能使除低n位外的更高位出现1. */ int can_put = allOne & ( ~(pos | left | right) ); /* 对于can_put每个为1的位,放置一个皇后,更新pos, left, right,然后继续下一步搜索。 */ while ( can_put ) // 只要put不为0,证明它还有为1的位,还有可能放皇后的位置 { int put = can_put & -can_put; // 这样运算,put只有can_put的最低位为1的位置为1,其他位置均为0。 dfs(pos|put, (left|put)<<1, (right|put)>>1); can_put ^= put; // 一个二进制位与1异或把该位取反,与0异或该位不变,故该语句把此次放置皇后的位置在can_put中置0(因为这个位置放置皇后的情况已经在此次循环中计算完了)。 } } /* 一个n×n的棋盘,在棋盘上摆n个皇后,求满足任意两个皇后不能在同一行、同一列或同一斜线上的方案数。 n:上述n 返回值:方案数 */ int getAnswer(int n) { ans = 0; allOne = (1 << n) - 1; // 得到一个低n位均为1,其他位为0的二进制。 dfs(0, 0, 0); // 开始棋盘上没有棋子,故pos、left、right的各位均为0。 return ans; } int main() { int n; cin >> n; cout << getAnswer(n) << endl; return 0; }
以上是关于图论 - 图的遍历 - 深度优先搜索 - n皇后问题的主要内容,如果未能解决你的问题,请参考以下文章