DFS与N皇后问题

DFS

什么是DFS

DFS是指深度优先遍历也叫深度优先搜索

它是一种用来遍历或搜索树和图数据结构的算法

注:关于树的一些知识可以去看《树的概念及基本术语》这篇文章

它会不断地沿着节点的深度方向(该深度方向为其邻接点的方向)进行遍历

DFS如何实现

DFS主要步骤有以下几步

  • 访问并从某节点
  • 向邻接点出发,访问路径向深处走
  • 若走到最深处还有节点没访问,则再回到该层访问该节点(回溯)
  • 依次重复上述步骤,直至所有路径都被访问(递归)

DFS时空复杂度

空间复杂度

DFS算法实际上是一个递归算法,需要借助一个递归工作栈

  • 空间复杂度:O(n)

时间复杂度

  • 时间复杂度:不确定

为什么不确定?

因为遍历图的过程实质上是对每个顶点找查其所有邻接点的过程,其耗费时间取决于所采用结构

下面给出常用的几种数据结构DFS时的时间复杂度

(注:n是图中结点的个数,e是图中边的个数。)

  • 邻接表 O(e+n)
  • 邻接矩阵 O(n^2)

N皇后问题

N皇后问题(HDU2553)

HDU 2553 N皇后问题

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。 输入:共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。 输出:共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。 输入样例:
1
8
5
0 输出样例:
1
92
10

经典DFS带来的问题

而经典的DFS,基本是将所有子节点全部扩展开,再选取最新的节点进行扩展。

但是对于N皇后来说,我们如果一一枚举,则有N的N次方种情况.

即使N=10,则有10^10种情况,我们还要在这些情况中进行筛选,这无疑需要巨大的计算

故:我们需要对DFS进行优化

回溯与减枝

我们可以让程序在某节点由某些条件就可以判断再进行继续展开并不符合要求,然后立即返回,达到回溯和减少树的枝干的生成(减枝)的目的,从而进行优化。

下面给出N=4时减枝的树状图解

问题分析

关键问题

关键问题:在扩展节点时如何去掉不符合条件的节点?

设左上角是(0,0),已经放好皇后是(i,j),不同行、列、斜线的新皇后是(r,c),则:

  • 横向不同行 i != r
  • 纵向不同列 j != c
  • 斜对角:从(i,j)向斜对角走a步,新坐标(r,c)有4种情况 (i-a,j-a) (i+a,j-a) (i-a,j+a) (i+a,j+a),即|i-r| = |j-c|。也就是说不再斜线上满足 |i-r| != |j-c|

其他问题

  • 由于给出N<=10,所以可以用打表的方式,将每种n取值对应的结果放到数组ans[n]中
  • 对于数组ans[]由于大小最方便设为11,n在0--10中取值一共11种情况。尽管我们可以忽略0定义成大小为10的数组(将n=1结果存放在ans[0]以此类推),但我们在取出数据时还要进行减法运算并不方便。
  • 对于在对特定的n取值分析时可用个tot变量来记录到达最深处情况的个数,由于循环是从0开始,我们只需要让r=n时tot自增1来记录并回溯
  • 数组col[r] = c,表示皇后放在第r行c列,我们可以用col[i] 来依次获得前几行皇后位置信息,故对于本题col[]数组定义最大为10就行

题解代码

#include <iostream>

using namespace std;

//tot记录每次n取特定值能放置n皇后情况的个数,每当n改变时tot重置为0
int n, tot = 0; //表示皇后存放位置 col[r] = c 表示第r行的皇后在第c列
int col[10]; //r为行,c为列
//check()用于检查新放置的皇后(r,c)是否和已经存放好的皇后冲突
//冲突返回false,不冲突返回true
bool check(int r, int c)
{
for (int i = 0; i < r; i++)
if (col[i] == c || (abs(col[i] - c) == abs(i - r))) //绝对值判断是否在同一斜线上
return false; //冲突返回false
return true; //不冲突返回true
} //r为检索的行
//对每行检索并放置皇后
void DFS(int r)
{
//若达到最底行(层)则新增1种情况,并返回(回溯)
if (r == n) {
tot++;
return;
} //对第r行(层)的每一列进行检索,若能放置则进入下一行(层)再从r+1行第0列向后检索放置依次类推
//若不能放置则本层次结束,递归然后回溯出去再改变上一层的列数,从该列再进行展开
for(int c=0;c<n;c++)
if (check(r, c)) //检查若放在该层该列是否与之前皇后冲突
{
col[r] = c; //记录再第r行c列放皇后,用于下一层向上检验冲突
DFS(r + 1); //继续放下一层皇后
} } int main()
{
//用于打表记录结果的数组
int ans[11]; memset(ans, 0, sizeof(0)); //算出n取所有值的答案
for (n = 0; n <= 10; n++)
{
memset(col, 0, sizeof(col)); //清空上一回的数组,计算下一个n皇后问题
tot = 0;
DFS(0);
ans[n] = tot; //打表,保存
} while (cin >> n)
{
if (n == 0)
return 0;
cout << ans[n] << endl;
} return 0;
}

数据

下面给出n从1到10取值的数据以供参考

n取1的结果为:1
n取2的结果为:0
n取3的结果为:0
n取4的结果为:2
n取5的结果为:10
n取6的结果为:4
n取7的结果为:40
n取8的结果为:92
n取9的结果为:352
n取10的结果为:724

复杂度

以下对于本题解法而言

  • check()复杂度 O(n!)
  • DFS()复杂度 O(N)
  • 总复杂度 O(N!·N)

对于N>11且N<=15可用数据结构舞蹈链较快解决

数学性质

  • N皇后问题在数学上是个NP完全问题,不存在多项式时间算法

本文参考

DFS与N皇后问题的更多相关文章

  1. 【DFS】n皇后问题

    回溯: 递归调用代表开启一个分支,如果希望这个分支返回后某些数据恢复到分支开启前的状态以便重新开始,就要使用到回溯技巧,全排列的交换法,数独,部分和,用到了回溯.下一个状态在开始之前需要利用到之前的状 ...

  2. HDU 1045 Fire Net(DFS 与8皇后问题类似)

    Fire Net Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  3. hdu2553N皇后问题(dfs,八皇后)

    N皇后问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  4. 用dfs求解八皇后问题

    相信大家都已经很熟悉八皇后问题了,就是指:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法.主要思路:按行进行深度优先搜索,在该 ...

  5. dfs 解决八皇后问题 以及其他图搜索问题

    33. N皇后问题 中文 English n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击(任意两个皇后不能位于同一行,同一列,同一斜线). 给定一个整数n,返回所有不同的n皇后问 ...

  6. DFS解决八皇后问题

    2019-07-29 16:49:15 #include <bits/stdc++.h> using namespace std; ][]; int tot; int check(int ...

  7. DFS,DP————N皇后问题

    C++代码 #include <iostream> using namespace std; const int N=20; int n; char g[N][N]; bool col[N ...

  8. 回溯(su)算法之N皇后问题

    这里回溯算法还要好好研究一下 试探一个位置是否有效,如果有效,试探下一个位置(DFS),如果无效则回退 1.定义一个解空间,存放一个解的空间 2.DFS(暂且认为是DFS) 这里N皇后用的是递归+回溯 ...

  9. 图论 List

    题目 #A 小 K 的农场 (Unaccepted)    #B 信息传递 (Unaccepted)    #C 最短路计数 (Accepted)    #D 通往奥格瑞玛的道路 (Accepted) ...

随机推荐

  1. VUE3 之 列表动画 - 这个系列的教程通俗易懂,适合新手

    1. 概述 老话说的好:可以为别人解决痛点的产品就是好产品. 言归正传,今天我们来聊聊 VUE 的列表动画. 2. 列表动画 2.1  列表中增加和删除元素 <style> .my-ite ...

  2. ArcMap操作随记(7)

    1.栅格分辨率调整 [重采样] 2.点集数据对插值模型精度检验 test数据→[子集要素](地统计分析)→train→[插值]→[多值提取至点]→[字段计算器](Abs([value]-[spline ...

  3. @weakify 与 @strongify 实现原理

    为了解决 Block 造成的循环引用,iOS 开发过程中常常使用 @weakify 与 @strongify 来解决这个问题.下面就来看下 @weakify 与 @strongify 的实现原理. 准 ...

  4. Hive框架

    1.什么是Hive? Hive 是基于Hadoop之上的数据仓库.2.什么是数据仓库? 数据仓库其实就是一个数据库 数据仓库是一个面向主题的,集成的,不可更新的,随时间不变化的数据集合,它用于支持 企 ...

  5. 一致性 Hash 在负载均衡中的应用

    介 一致性Hash是一种特殊的Hash算法,由于其均衡性.持久性的映射特点,被广泛的应用于负载均衡领域,如nginx和memcached都采用了一致性Hash来作为集群负载均衡的方案.本文将介绍一致性 ...

  6. ClickHouse镜像在阿里云镜像站首发上线

    镜像下载.域名解析.时间同步请点击阿里云开源镜像站 简介 ClickHouse是开源.高性能的列式OLAP的数据库管理系统(DBMS).使用SQL进行实时分析. ClickHouse可以做用户行为分析 ...

  7. 提升组件库通用能力 - NutUI 在线主题定制功能探索

    开发背景 NutUI 作为京东风格的组件库,已具备 H5 和多端小程序开发能力.随着业务的不断发展,组件库的应用场景越来越广.在公司内外面临诸如科技.金融.物流等各多个大型团队使用时,单一的京东 AP ...

  8. TiDB 5.0认证指南之PCTA PCTP

    1. TiDB简介 TiDB 是 PingCAP 公司自主设计.研发的开源分布式关系型数据库,是一款同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analyt ...

  9. Spring bean 和单例bean的线程安全

    Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).prototype(原型).request.session和global session,5种作用域说 ...

  10. RocketMQ下载安装

    windows下RocketMQ下载安装教程   一.下载 1.官网下载:http://rocketmq.apache.org/dowloading/releases/ 2.百度网盘下载:https: ...