搜索(dfs&bfs)

明天周日没课,但是上个周的课基本一节课都没听,总不能挂科吧...所以明天还是去补一下算了...

现在是晚上十二点14分,还一点不困(白天咖啡喝多了?),正好今天写01bfs双端队列的时候发现太久没写连bfs和dfs都快忘了....所以写篇博文记录一下吧...

正文:

dfs(深度优先搜索) 从上到下遍历每一种可能,到达底部后又回溯,其采用栈的方式,优点是空间复杂度低,但时间复杂度较高,且不具有最短路的性质。

例1 全排列:

输入一个正整数n(n<=9),按字典序从小到大输出1到n的全排列。

#include<iostream>
#include<cstdio>

using namespace std;

int n;
int a[10];//记录排列
bool vis[10];//判断数字是否已经使用

void dfs(int u)
{
	if (u == n) {
		for (int i = 0; i < n; i++) printf("%d", a[i]);
		printf("\n");
        return;
	}
	for (int i = 1; i <= n; i++)
	{
		if (!vis[i]) {
			vis[i] = 1;
			a[u] = i;
			dfs(u + 1);
			vis[i] = 0;
		}
	}
}
int main()
{
	scanf("%d", &n);
	dfs(0);
	return 0;
}

例2 走出迷宫

来源:牛客网

题目描述

小明现在在玩一个游戏,游戏来到了教学关卡,迷宫是一个N*M的矩阵。

小明的起点在地图中用“S”来表示,终点用“E”来表示,障碍物用“#”来表示,空地用“.”来表示。

障碍物不能通过。小明如果现在在点(x,y)处,那么下一步只能走到相邻的四个格子中的某一个:(x+1,y),(x-1,y),(x,y+1),(x,y-1);

小明想要知道,现在他能否从起点走到终点。

输入描述

本题包含多组数据。
每组数据先输入两个数字N,M
接下来N行,每行M个字符,表示地图的状态。
数据范围:
2<=N,M<=500
保证有一个起点S,同时保证有一个终点E.

输出描述

每组数据输出一行,如果小明能走到终点输出"Yes",不能输出"No"

一道简单的迷宫题,代码如下

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define endl '\n'
const int maxn = 505;
int dx[] = { 0,0,1,-1 }; //下一步走的方向
int dy[] = { 1,-1,0,0 };
bool vis[maxn][maxn]; //该点是否走过
bool flag = 0;
int m = 0, n = 0;
char s[maxn][maxn]; //地图
void dfs(int x, int y)
{
	for (int i = 0; i < 4; i++) {
		int mx = x + dx[i];
		int my = y + dy[i];
		if (mx<1 || mx>m) continue; //越界
		if (my<1 || my>n) continue;
		if (vis[mx][my] == 1||s[mx][my]=='#') continue; //已经走过了或者是陷阱
		vis[mx][my] = 1;
		if (s[mx][my] == 'E') {
			cout << "Yes" << endl;
			flag = 1;
		}
		dfs(mx, my);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int x = 0, y = 0;
	while (cin>>m>>n)
	{
		memset(vis, 0, sizeof(vis));
		flag = 0;
		for (int i = 1; i <= m; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				cin >> s[i][j];
				if (s[i][j] == 'S') {
					x = i;
					y = j;
					vis[i][j] = 1;
				}
			}
		}
		dfs(x, y);
		if (!flag) cout << "No" << endl;
	}
	return 0;
}

bfs(宽度优先搜索) 宽搜使用队列实现,空间复杂度较大,但是时间复杂度较小,并且具有最短路的性质。

登录—专业IT笔试面试备考平台_牛客网​​​​​​

题解是以前刚学的时候写的,有些地方不太好,但是不想改了...

代码如下:

#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn = 1e3+5;
int m = 0;
char s[maxn][maxn][maxn];   //地图大小
bool vis[maxn][maxn][maxn]; //记录走过的点
int dx[] = { 1,-1,0,0,0,0 };   //走向
int dy[] = { 0,0,1,-1,0,0 };
int dz[] = { 0,0,0,0,1,-1 };
struct node {
	int x, y, z, num;
}now,nextt;   //当前步和下一步
inline bool check(int xx, int yy, int zz) //是否越界
{
    return xx > 0 && xx <= m && yy > 0 && yy <= m && zz>0 && zz <= m; 
}
int bfs(int x, int y, int z)
{
	queue<node>q;
	int xx, yy, zz;
	now.x = x;
	now.y = y;
	now.z = z;
	now.num = 1;
	q.push(now);  //从起点开始
	while (!q.empty())
	{
		now = q.front();
        if (now.x==m&&now.y==m&&now.z==m) return now.num;
		q.pop();
		for (int i = 0; i < 6; i++)  //遍历四个方向
		{
			xx = now.x + dx[i];
			yy = now.y + dy[i];
			zz = now.z + dz[i];
			if (check(xx,yy,zz) && !vis[xx][yy][zz] && s[xx][yy][zz] != '*')
			{
				nextt.x = xx;
				nextt.y = yy;
				nextt.z = zz;
				nextt.num = now.num + 1;
               // cout<<now.x<<" "<<now.y<<" "<<now.z<<"  "<<now.num<<endl;
               // cout<<nextt.x<<" "<<nextt.y<<" "<<nextt.z<<"  "<<nextt.num<<endl;
				vis[xx][yy][zz] = 1;
				q.push(nextt);
			}
        //    if (xx==m&&yy==m&&zz==m) return nextt.num;
		}
	}
	return -1; //无法到达终点
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie();
	cin >> m;
	for (int i = 1; i <= m ; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			for (int k = 1; k <= m; k++) cin >> s[i][j][k];
		}
	}
    vis[1][1][1]=1;
	int res = bfs(1, 1 ,1);
	cout << res << endl;
	return 0;
}

基本的搜索就写到这儿,其他的以后补充.....

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值