明天周日没课,但是上个周的课基本一节课都没听,总不能挂科吧...所以明天还是去补一下算了...
现在是晚上十二点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(宽度优先搜索) 宽搜使用队列实现,空间复杂度较大,但是时间复杂度较小,并且具有最短路的性质。
题解是以前刚学的时候写的,有些地方不太好,但是不想改了...
代码如下:
#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;
}
基本的搜索就写到这儿,其他的以后补充.....