详解深度优先搜索与回溯
严格来说,搜索也是一种暴力枚举策略,传统的枚举需要固定for循环的层数,但是这样不能随意增减枚举层数,本文将介绍一种新的利用递归的方式枚举每个可能的选项,如果合法就继续下一个,如果所有选项都不合法就退回并尝试更换上一个的选项,继续枚举。这种方式就是回溯算法,常用深度优先搜索实现:
先来看一道模板题:
排列数字
给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出。
输入格式:共一行,包含一个整数 n。
输出格式:按字典序输出所有排列方案,每个方案占一行。
数据范围:1≤n≤7
思路:
if(book[i]==0) // 即未使用过{a[step]==i;book[i]==1; }
那么下一个空位该如何处理呢?
void dfs(int step)
{for(int i=i;i<=n;i++)// 空位上可选择的数为1到n{if(book[i]==0){a[step]==i;book[i]==1;}}
}
void dfs(int step)
{for(int i=i;i<=n;i++){if(book[i]==0){a[step]==i;book[i]==1;dfs(step+1);book[i]==0; // 这是重要的一步,收回已经使用的数也就是第step个数}}
}
void dfs(int step)
{if(step==n+1){for(int i=1;i<=n;i++)cout<<a[i]<<' ';cout<<endl;return; // 返回以前的一步}for(int i=i;i<=n;i++){if(book[i]==0){a[step]==i;book[i]==1;dfs(step+1);book[i]==0;}}
}
#include<iostream>
using namespace std;
const int N=100;
int a[N],book[N],n;void dfs(int step)
{if(step==n+1){for(int i=1;i<=n;i++)cout<<a[i]<<' ';cout<<endl;return;}for(int i=1;i<=n;i++){if(book[i]==0){a[step]=i;book[i]=1;dfs(step+1);book[i]=0;}}
}
int main()
{cin>>n;dfs(1);return 0;
}
由此可得深搜的基本模型:
void dfs(int step)
{if(所有空被填完){记录答案/判断最优解 return; }for(枚举选项) if(合法) {记录现场 dfs(step+1);恢复现场 }
}
下面再来看一道经典题目:
八皇后
一个如下的6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列 2 4 6 1 3 5 来描述,第 i 个数字表示在第 i 行的相应位置有一个棋子,如下:
行号1 2 3 4 5 6
列号 2 4 6 1 3 5
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 3 个解。最后一行是解的总个数。输入格式:一行一个正整数 n,表示棋盘是 n×n 大小的。
输出格式:前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
思路:
考虑到每一行、列只能放一个,对于行,我们可以遍历,对于列,我们可以递归,最后判断是否在同一条斜线上即可,斜线的判断是本题的难点,考虑到它们的斜率都为1,所以不同的斜线截距必然不同,我们可以套用初中的直线方程:y=x+b → b=y-x(对角) y=-x+b→b=y+x(反对角)但是考虑到数组名不能为负,而且截距只是为了区分并无实际意义,所以对角的截距我们需要加上一个较大的数,代码:
#include<bits/stdc++.h>
using namespace std;//column列 diagonal对角 antidiagonal反对角
//y=x+b;b=y-x dg
//y=-x+b;b=y+x adg
const int N=15;
int a[N][N];
int col[N],dg[N*2],adg[N*2];
int res,n;
void dfs(int u) // 从第u行开始
{if(u==n+1) { if(res<3){for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++)if(a[i][j]==1)cout<<j<<' ';}cout<<endl; } res++; }for(int i=1;i<=n;i++) //记录列 if(!col[i]&&!dg[i-u+n]&&!adg[u+i]){a[u][i]=1;col[i]=1;dg[i-u+n]=1;adg[u+i]=1;dfs(u+1);a[u][i]=0;col[i]=0;dg[i-u+n]=0;adg[u+i]=0; } }
int main()
{cin>>n;dfs(1);cout<<res<<endl;return 0;
}
_ _ _ + _ _ _ = _ _ _将数字1到9填进空位,每个数只能用一次,问一共有几种组合?
直接上代码:
#include<iostream>
using namespace std;
const int N=100;
int a[N],book[N],res;void dfs(int step)
{if(step==10){if(a[1]*100+a[2]*10+a[3]+a[4]*100+a[5]*10+a[6]==a[7]*100+a[8]*10+a[9]){printf("%d%d%d+%d%d%d=%d%d%d\n",a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);res++;return;}}for(int i=1;i<10;i++){if(book[i]==0){a[step]=i;book[i]=1;dfs(step+1);book[i]=0;}}
}
int main()
{dfs(1);cout<<res/2<<endl; //会出现a+b=c||b+a=c的重复情况return 0;
}
详解深度优先搜索与回溯相关推荐
- 深入浅出,详解深度优先搜索(DFS)
深度优先搜索 如果把深度优先搜索比作一个人的话,那么这个人是一个执着的人,甚至倔强,不把一条路走到底不会返回(回溯),虽然执着倔强,但是他不傻,如果在探索的途中发现这条路走下去没有希望他会提前返回(剪 ...
- 深度优先搜索c语言详解,深度优先搜索 — C语言版
思路:找一个入口结点,然后搜索该结点的第一个相邻结点,再搜索该相邻结点的第一个相邻结点,依次往下寻找 - - ,直到所有结点都被遍历到,算法结束,退出. #include #define MAX 10 ...
- 以SIGSEGV为例详解信号处理(与栈回溯)
以SIGSEGV为例详解信号处理(与栈回溯) 信号是内核提供的向用户态进程发送信息的机制, 常见的有使用SIGUSR1唤醒用户进程执行子程序或发生段错误时使用SIGSEGV保存用户错误现场. 本文以S ...
- Nuist集训队作业:深度优先搜索(回溯算法)
Nuist集训队第一次作业:深度优先搜索(回溯算法) 引例 深搜基本思想及回溯算法模板 P1706 全排列问题 P1219 八皇后 P1605 迷宫 P1101 单词方阵 小结 引例 国际西洋棋棋手马 ...
- C++解题报告:详解经典搜索难题——八数码问题( 双向BFS A* 求解)
引言 AC这道八数码问题,你和楼教主就是兄弟了... 题目描述 在一个3*3的九宫格棋盘里,放有8个数码,数码的数字分别是1~8.棋盘中还有一个位置是空着的,用0表示.可以通过在九宫格里平移数码来改变 ...
- 一文详解 | 开放搜索兼容Elasticsearch做召回引擎
简介:开放搜索发布开源兼容版,支持阿里云Elasticsearch做搜索召回引擎,本文详细介绍阿里云ES用户如何通过接入开放搜索兼容版丰富行业分词库,提升查询语义理解能力,无需开发.算法投入,即可获得 ...
- 回溯算法详解:理论+基础类回溯题解
文章目录 五:括号生成问题 六:组合总和(点击跳转) 七:子集问题(点击跳转) 五:括号生成问题 这个问题也比较经典,题目的要求是让你生成所有可能的并且 有效的 括号组合. 对于括号问题,两个特性,请 ...
- 计算机 查找 功能的使用,详解电脑搜索快捷键是什么?
办公软件Office使用经常要替换或更改文档上面的字眼,那么如何快速查找文档上面的相关的全部关键词呢?其实Office软件提供内置的搜索查找功能,能够快速定位关键词位置以及个数,甚至快速替换等等,下面 ...
- elasticsearch系列四:搜索详解(搜索API、Query DSL)
一.搜索API 1. 搜索API 端点地址 从索引tweet里面搜索字段user为kimchy的记录 GET /twitter/_search?q=user:kimchy 从索引tweet,user里 ...
最新文章
- 每日英语:Relationship Repair: 10 Tips for Thinking Like a Therapist
- VC++ 访问数据库实例详解图解
- 检查本地服务器是否配置成功
- 【Flask】sqlalchemy 排序
- 【要闻】Kubernetes安全问题严峻、Linux v5.4安全性浅谈
- Java EE 6示例– Galleria第2部分
- 理论基础 —— 排序 —— 鸡尾酒排序
- Google 也要“勒紧腰带”过日子了!
- $.ajax+php实战教程之下拉时自动加载更多文章原理分析
- GPS 相关知识科普
- Onvif客户端与服务器通信时鉴权的自实现
- favicon.ico图标在线制作+ico下载
- [亲自试过有效] 错误1606。无法访问网络位置
- 计算机老提示安全证书到期,安全证书过期,教您怎么解决网站安全证书过期
- iphone邮件服务器 263,在iphone上怎么设置263邮箱
- (2.2)【窃密型木马-广外幽灵】简介、使用
- 在移动设备上使用M3G编程教程(转)
- matlab 柱状图不同颜色(取巧哈)
- python-读取和保存npy文件
- DDD微服务架构设计第四课 DDD指导微服拆分和落地实现
热门文章
- linux中 代表什么,Linux中的$1代表什么?
- 写给我的2014——也写给我即将逝去的研究生生涯
- 计算机音频服务未运行怎么办,音频服务未运行win10如何处理_win10电脑显示音频服务未运行怎么解决...
- 300服务器维护,怎么7月24号300英雄服务器进不去,一直在维护,要维护到几点啊
- 【jdbc】spring
- 数据结构(廿六) -- C语言版 -- 图 - 图的遍历 -- 邻接表 - 深度/广度优先遍历/搜索(DFS、BFS)
- 保险业务与系统——LOMA 290 保险公司运营——第十四讲——财务管理
- 我们应该用什么酒袋来安全地运输葡萄酒?
- SSL协议、TLS协议,使用哪一种更安全?
- 5分钟掌握智联招聘网站爬取并保存到MongoDB数据库