dfs
dfs的话,其实可以看做是一个递归树
利用栈或者标记数组进行回溯
算法思路模版
int(void) dfs(int x)
{
//递归结束的判断条件
//标记位置
//dfs(int x)
//恢复现场(有些题可不用,比如迷宫问题)
}
模版题
此模版题,我写了2种dfs的算法,
一种是枚举四个方向的位置,然后再dfs
一种是直接dfs四个方向
/*#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 25;
char g[N][N];
int st[N][N];
//(1, 0) (-1, 0) (0, -1) (0, 1)
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, -1, 1};
int n, m;
int ans;
//版本一: 枚举当前位置的四个方向,然后dfs
int dfs1(int x, int y)
{
int res = 1;
//标记当前位置
st[x][y] = 1;
// 枚举当前位置的四个方向
for(int i = 0; i < 4; i++)
{
int a = x + dx[i];
int b = y + dy[i];
//1.判断枚举的位置是否合法
//2.如果合法,标记这个位置,然后继续dfs
//判断是否越界
if(a < 0 || a >= m || b < 0 || b >= n) continue;
//判断是否是可走
if(g[a][b] == '#') continue;
//判断是否遍历过
if(st[a][b]) continue;
//当前枚举的这个位置合法
//标记枚举的这个位置
st[a][b] = 1;
//继续dfs,枚举的位置(a, b)
res += dfs1(a, b);
}
return res;
}
//版本二:直接递归四个方向
void dfs2(int x, int y)
{
//递归结束的条件 (return)
if(x < 0 || x >= m || y < 0 || y >= n) return;
if(st[x][y]) return;
if(g[x][y] == '#') return;
ans++;
//不要忘记,标记当前位置
st[x][y] = 1;
dfs2(x + 1, y);
dfs2(x - 1, y);
dfs2(x, y + 1);
dfs2(x, y - 1);
//走格子,不需要恢复现场
}
int main()
{
while(cin >> n >> m, n || m)
{
for(int i = 0; i < m; i++) scanf("%s",g[i]);
//有多组数据,注意ans要初始化
ans = 0;
//找到起点
int x, y;
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
if(g[i][j] == '@')
x = i, y = j;
//这里注意:
//输入多个数据集合,每个数据集合的,标记数组都要进行初始化
memset(st, 0, sizeof st);
//cout << dfs1(x, y) << endl;
//版本二:
dfs2(x, y);
cout << ans << endl;
}
return 0;
}
*/
bfs
求最小值,一般采用bfs算法,而不是dfs算法
算法思路模版
/*
bfs: 一般模板
思想(类似树的层次遍历,取出队列的头部元素,然后将与这个头部元素
相关的,放到队尾里去)
void bfs()
{
queue<int> q;//一般用stl库中的queue来实现队列比较方便
q.push(起点S);//将初始状态入队
//标记初始状态已入队。
while(!q.empty())//队列不为空就执行入队出队操作
{
top = q.front();//取出队首
q.pop();//队首出队
for (枚举所有可扩展的状态)
{
if (check())//状态合法
{
q.push(temp);//状态入队
//标记成已入队。
}
}
}
*/
模版题