搜索(普通DFS和BFS)

既然讲课做了笔记,那么干脆把笔记上传一下啦!

1.DFS和BFS之间的区别、联系:

(1)深搜和宽搜都可以对我们的整个空间进行遍历、搜索

​ 数据结构 使用空间

DFS 栈 O(h)

BFS 队列 O(2^h) 最短路

2.深度优先搜索(DFS)

例题:

1.排列数字(简单)

题目:

给定一个整数 n,将数字 1∼n排成一排,将会有很多种排列方法。

现在,请你按照字典序将所有的排列方法输出。

输入格式

共一行,包含一个整数 n。

输出格式

按字典序输出所有排列方案,每个方案占一行。

数据范围

1≤n≤7

输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
AC代码:
`#include<iostream>`
`#include<cstdio>`

`using namespace std;`

`const int N=10;`

`int n;`
`int path[N];//用一个全局数组来存一下状态,路径保存` 
`bool st[N];//判断哪些数组用过了` 

`void dfs(int u)`
`{`
	`if(u==n)//当走到第n个的位置时` 
	`{`
		`for(int i=0;i<n;i++)`
		`{`
			`printf("%d ",path[i]);`
		`}`
		`puts("");//每一个方案后面都要输出一个空行` 
		`return ;`
	`}`

`for(int i=1;i<=n;i++)//当u<n时,说明还没有填完,则需要枚举一下当前这个位置可以填哪些数` 
`{`
	`if(!st[i])//找一个没有被用过的数` 
	`{`
		`path[u]=i;`
		`st[i]=true;//记录一下i已经被用过了` 
		`dfs(u+1);//递归下一层` 
		`st[i]=false;//恢复现场` 
	`}`
`}`

`}`

`int main()`
`{`
	`cin>>n;//读入一个n` 

  `dfs(0);//从第0的位置开始看` 

` return 0;`

`}`

2. n - 皇后问题(中等)

题目:

n−皇后问题是指将 n 个皇后放在 n×n的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。

1_597ec77c49-8-queens.png

现在给定整数 n,请你输出所有的满足条件的棋子摆法。

输入格式

共一行,包含整数 n。

输出格式

每个解决方案占 n行,每行输出一个长度为 n的字符串,用来表示完整的棋盘状态。

其中 . 表示某一个位置的方格状态为空,Q 表示某一个位置的方格上摆着皇后。

每个方案输出完成后,输出一个空行。

注意:行末不能有多余空格。

输出方案的顺序任意,只要不重复且没有遗漏即可。

数据范围

1≤n≤9

输入样例:
4
输出样例:
.Q..
...Q
Q...
..Q.

..Q.
Q...
...Q
.Q..
AC代码:

***第一种搜索顺序:***

`#include<iostream>`
`#include<cstdio>`

`using namespace std;`

`const int N=20;`

`int n;`
`char g[N][N];`
`bool col[N],dg[N],udg[N];`

`void dfs(int u)`
`{`
	`if(u==n)//说明已经找到一组方案` 
	`{`
		`for(int i=0;i<n;i++)`
		`{`
			`puts(g[i]);`
		`}`
		`puts("");//每一个方案后面都要输出一个空行` 
		`return ;`
	`}`

`for(int i=0;i<n;i++)`
`{`
	`if(!col[i]&&!dg[u+i]&&!udg[n-u+i])`
	`{`
		`g[u][i]='Q';`
		`col[i]=dg[u+i]=udg[n-u+i]=true;` 
		`dfs(u+1);//递归下一层` 
		`col[i]=dg[u+i]=udg[n-u+i]=false;//恢复现场` 
		`g[u][i]='.';`
	`}`
`}`

`}`

`int main()`
`{`
	`cin>>n;//读入一个n` 
	`for(int i=0;i<n;i++)`
	`{`
		`for(int j=0;j<n;j++)`
		`{`
			`g[i][j]='.';`
		`}`
	`}`
	`dfs(0);//从第0的位置开始看` 

`return 0;`

`}`

***第二种搜索顺序(更加原始):***

`#include<iostream>`
`#include<cstdio>`

`using namespace std;`

`const int N=20;`

`int n;`
`char g[N][N];`
`bool row[N],col[N],dg[N],udg[N];`

`void dfs(int x,int y,int s)`
`{//首先当前皇后的顺序一定不会超过n` 
	`if(y==n)
	{
		y=0,x++;
	}
	if(x==n)//说明我们已经枚举完最后一行了,就要停止了` 
	`{`
		`if(s==n)//如果此时我们摆的皇后的次数等于n了,说明我们找到了一组解` 
		`{`
			`for(int i=0;i<n;i++)//输出这组解` 
			`{`
				`puts(g[i]);`
			`}`
			`puts("");`
		`}`
		`return ;`
	`}`
	`//枚举一下当前格子的两种选择`

`//第一种选择是不放皇后`
`dfs(x,y+1,s);//直接递归到下一个格子就可以了`

`// 第二种选择放皇后(这就需要判断一下)` 
`if(!row[x]&&!col[y]&&!dg[x+y]&&!udg[x-y+n]) //首先这一行不能有皇后,其次,这一列不能有皇后,并且对角线上不能有皇后,并且反对角线上也不能有皇后` 
`{`
	`g[x][y]='Q';` 
	`row[x]=col[y]=dg[x+y]=udg[x-y+n]=true;//都放上了皇后`
	`dfs(x,y+1,s+1);//然后递归到下一层` 
	`row[x]=col[y]=dg[x+y]=udg[x-y+n]=false;//恢复现场` 
	`g[x][y]='.';`
`}`

`}`
`int main()`
`{`
	`cin>>n;//读入一个n` 
	`for(int i=0;i<n;i++)`
	`{`
		`for(int j=0;j<n;j++)`
		`{`
			`g[i][j]='.';`
		`}`
	`}`
	`dfs(0,0,0);//从左上角开始搜,记录一下当前有多少个皇后` 

`return 0;`

`}`

3.宽度优先搜索(BFS)

基本框架:

queue ← 初始状态

while queue不空

{

​ t ← 队头

​ 拓展 t

}

例题:

1.走迷宫(简单)

题目:

给定一个 n×m的二维整数数组,用来表示一个迷宫,数组中只包含 0 或 1,其中 0表示可以走的路,1表示不可通过的墙壁。

最初,有一个人位于左上角 (1,1)处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。

请问,该人从左上角移动至右下角 (n,m)处,至少需要移动多少次。

数据保证 (1,1)处和 (n,m)处的数字为 0,且一定至少存在一条通路。

输入格式

第一行包含两个整数 n 和 m。

接下来 n行,每行包含 m 个整数(0 或 1),表示完整的二维数组迷宫。

输出格式

输出一个整数,表示从左上角移动至右下角的最少移动次数。

数据范围

1≤n,m≤100

输入样例:
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出样例:
8
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

typedef pair<int,int> PII;

const int N=110;

int n,m;
int g[N][N];//存地图` 
int d[N][N];//存每一个点到起点的距离`
PII q[N*N];

int bfs()
{
	int hh=0,tt=0;
	q[0]={0,0};

memset(d,-1,sizeof d);//首先把所有距离初始化为-1,表示我们没有走过 
d[0][0]=0;//表示已经走过了

int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};

while(hh<=tt)//while队列不空
{
	pair<int,int> t=q[hh++];//每一次取出来对头元素
		
	for(int i=0;i<4;i++)//每一次枚举一下4个方向
	{
		int x=t.first+dx[i],y=t.second+dy[i];//x表示沿着这个方向走会走到哪个点
		 
		if(x >= 0&& x <n &&y >= 0 && y < m && g[x][y]==0&&d[x][y]==-1)//如果沿着这个方向走的话,它在边界内并且这个点等于0是可以走的 并且还没有走过的话,就把它扩展出来 
	 {
			d[x][y]=d[t.first][t.second]+1;
			q[++tt]={x,y};//把刚才的那个点加进去 
		}
	}
}
return d[n-1][m-1];//然后把右下角的点的距离输出

}

int main()
{
	cin>>n>>m;

for(int i=0;i<n;i++)//先读入整个地图
{
	for(int j=0;j<m;j++)
	{
		cin>>g[i][j];
	}
}

cout<<bfs()<<endl;//直接输出bfs 

return 0;

}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值