图论 - 图的遍历 - 深度优先搜索 - 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;
}

原文地址:https://www.cnblogs.com/fyqq0403/p/10588940.html

时间: 2024-07-29 01:23:44

图论 - 图的遍历 - 深度优先搜索 - n皇后问题的相关文章

数据结构:图的遍历--深度优先、广度优先

图的遍历:深度优先.广度优先 遍历 图的遍历是指从图中的某一顶点出发,按照一定的策略访问图中的每一个顶点.当然,每个顶点有且只能被访问一次. 在图的遍历中,深度优先和广度优先是最常使用的两种遍历方式.这两种遍历方式对无向图和有向图都是适用的,并且都是从指定的顶点开始遍历的.先看下两种遍历方式的遍历规则: 深度优先 深度优先遍历也叫深度优先搜索(Depth First Search).它的遍历规则:不断地沿着顶点的深度方向遍历.顶点的深度方向是指它的邻接点方向. 具体点,给定一图G=<V,E>,

[算法小练][图][拓扑排序+深度优先搜索] 平板涂色问题

说在前面 本题是一道经典题目,多做经典题目可以节省很多学习时间,比如本题就包含了许多知识:回溯+剪枝+拓扑排序+深度优先搜索.[动态规划方法另作讨论] 关键代码 题: CE数码公司开发了一种名为自动涂色机(APM)的产品.它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色. 为了涂色,APM需要使用一组刷子.每个刷子涂一种不同的颜色C.APM拿起一把有颜色C的刷子,并给所有颜色为C且符合下面限制的矩形涂色: 为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂

Java用邻接矩阵实现图并进行深度优先搜索

先定义节点类 class Vertex{ char label; boolean wasVisited; public Vertex(char label){ this.label = label; wasVisited = false; } } 图: class Graph{ private final int MAX_VERTS = 20; private Vertex vertexList[];//节点列表 private int adjMat[][];//邻接矩阵 private int

深度优先搜索——八皇后问题

代码:(控制台打印不了92种情况,只打印前10种) 1 #include<iostream> 2 #include<string> 3 #include<windows.h> 4 #define ok 1 5 #define error 0 6 using namespace std; 7 8 9 int a[9][9]={0}; 10 int num=0; 11 12 int Ifblock(int x,int y) //判断有没有产生冲突 13 { 14 int i

图的遍历---深度优先遍历与广度优先遍历

对下图进行遍历,分别采用深度优先和广度优先 1.深度优先遍历的主要思想:首先从一个未被访问的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点: 当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的顶点,直到所有顶点都被访问. 显然,深度优先遍历是沿着图的某一条分支遍历直到末端,然后回溯,再沿着另一条进行同样的遍历,直到所有顶点被访问. /*深度优先搜索算法遍历图的各个顶点*/ #include<stdio.h> int n, sum, book[101]; int e[101][101

图的遍历(深度优先与广度优先搜索两种方案)

1.图的遍历--深度优先搜索 import java.util.Scanner ; public class Map{ static int n ; static int m ; static int[] book ; static int[][] e ; public static void mapDfs(int cur){ //深度优先搜索思想核心: System.out.print(cur + " ") ; for (int i=1;i<=n;i++) { if (e[cu

&quot;《算法导论》之‘图’&quot;:深度优先搜索、宽度优先搜索及连通分量

本文兼参考自<算法导论>及<算法>. 以前一直不能够理解深度优先搜索和广度优先搜索,总是很怕去碰它们,但经过阅读上边提到的两本书,豁然开朗,马上就能理解得更进一步.  1. 深度优先搜索  1.1 迷宫搜索 在<算法>这本书中,作者写了很好的一个故事.这个故事让我马上理解了深度优先搜索的思想. 如下图1-1所示,如何在这个迷宫中找到出路呢?方法见图1-2. 图1-1 等价的迷宫模型 探索迷宫而不迷路的一种古老办法(至少可以追溯到忒修斯和米诺陶的传说)叫做Tremaux搜

图的遍历 (dfs与bfs)x

遍历是很多图论算法的基础,所谓图的遍历( graph traversal),也称为搜索( search),就是从图中某个顶点出发,沿着一些边访遍图中所有的顶点,且使每个顶点仅被访问一次.         遍历可以采取两种方法进行:         深度优先搜索( DFS: depth first search):         广度优先搜索( BFS: breadth first search). 对图进行存储与遍历: 输入: 第一行:顶点数n. 第二行:边数m. 以下m行,每行两个顶点编号u

深度优先搜索

在图中的深度优先搜索,由于避免回路的产生,设置visit数组. 有两种深度优先的应用场景.一种是用于最优解的寻找,即到达目的地的最优解.这时需要设置全局的一个数组,还有变量,来储存路径.通过与别的方法的比较,获取最优解. 第二种是染色问题,只要求全部遍历,没有最优的要求. 还有哈希的用法.当需要记录拥有共同数字特征的一些属性时,就可以使用哈希数组.使用时按照属性的含义寻找.如二叉树某层的数量.