DFS和BFS典型例题
1、DFS
DFS模板:
void dfs()//参数用来表示状态
{
if(到达终止状态)//递归出口
{
...//根据题意来添加
return;
}
if(越界或者不合法状态)
return;
else
{
for(扩展方式)
{
if(扩展方式所达到的合法状态)
{
...//根据题意来添加
vis[i]=1;//标记
修改(剪枝)
dfs();
vis[i]=0;
//是否还原标记根据题意来
//如果加上还原标记,就是回溯算法
}
}
}
}
- 全排列
#include <stdio.h>
#include <string.h>
int v[1005], a[1005], n;
void dfs(int c)
{
if (c == n)
{
for (int i = 0; i < n; i++)
printf("%d", a[i]);
printf("\n");
}
else
{
for (int i = 1; i <= n; i++)
{
if (!v[i])
{
v[i] = 1;
a[c] = i;
dfs(c + 1);
v[i] = 0;
}
}
}
}
int main()
{
while (scanf("%d",&n) != EOF)
{
memset(v, 0, sizeof(v));
memset(a, 0, sizeof(a));
dfs(0);
}
return 0;
}
- 素数环
#include <stdio.h>
#include <string.h>
int a[25], v[25], k = 1, n;
//用来判断是否为素数
int isprime(int a)
{
int flag = 1;
if (a == 1)
return 0;
else if (a == 2)
return 1;
else
{
for (int i = 2; i < a; i++)
{
if (a % i == 0)
{
flag = 0;
break;
}
}
if (flag)
return 1;
else
return 0;
}
}
void dfs(int c)
{
if (c == n && isprime(a[0] + a[c - 1]))
{
printf("%d", a[0]);
for (int i = 1; i < n; i++)
printf(" %d", a[i]);
printf("\n");
}
else
{
for (int i = 2; i <= n; i++)
{
if (!v[i] && isprime(i + a[c - 1]))
{
v[i] = 1;
a[c] = i;
dfs(c + 1);
v[i] = 0;
}
}
}
}
int main()
{
while (scanf("%d", &n) != EOF)
{
memset(v, 0, sizeof(v));
memset(a 0, sizeof(a));
printf("Case %d:\n", k++);
a[0] = 1;
dfs(1);
printf("\n");
}
return 0;
}
- 走迷宫
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char maze[10][10] = {"000S0", "0XXX0", "00000", "0XXX0", "0000E"};
int vis[10][10];
int sum = 0;
/*
边解条件
1、走到'E',停止计数
2、不能够非法访问,越界
3、走过的点不要重复走
4、遇到墙,结束
*/
void solve(int x, int y)
{
if (maze[x][y] == 'E')
{
sum++;
return;
}
if (x == -1 || x = 5 || y == -1 || y == 5)
return;
if (vis[x][y] == 1)
return;
if (maze[x][y] == 'X')
return;
vis[x][y] = 1;
solve(x + 1, y);
solve(x, y + 1);
solve(x - 1, y);
solve(x, y - 1);
vis[x][y] = 0;
}
int main()
{
memset(vis, 0, sizeof(vis));
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
if (maze[i][j] == 'S')
solve(i, j);
}
}
printf("%d", sum);
return 0;
}
- 油菜田
#include <stdio.h>
#include <string.h>
char a[105][105], v[105][105];
int n, m;
void dfs(int x, int y) //dfs主要的作用是为了标记属于同一个图上的@,所以不需要回溯
{
if (x < 0 || y > 0 || x >= n || y >= m)
return;
if (a[x][y] == '*' || v[x][y])
return;
v[x][y] = 1;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (i == 0 && j == 0)
continue;
dfs(x + i, y + j);
}
}
}
int main()
{
while (scanf("%d %d", &n, &m) != EOF && n != 0 && m != 0)
{
memset(v, 0, sizeof(v));
memset(a, 0, sizeof(a));
getchar();
for (int i = 0; i < n; i++)
scanf("%s", a[i]);
int cnt = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (a[i][j] == '@' && !v[i][j]) //类似于数据结构中图那章,主要是有些图没有联通
{
dfs(i, j);
cnt++;
}
}
}
}
}
- wjw和ly的双人游戏*
#include <stdio.h>
#include <string.h>
//攻破城堡i需要先攻破f[i]
int f[15], a[15], v[15];
int n, m, ans;
int max(int a, int b)
{
return a > b ? a : b;
}
int find() //用来计算满足城堡数量时的宝物数量
{
int sum = 0, cnt = 0;
for (int i = 1; i <= n; i++)
{
if (v[i]) //只要这个城堡被选择了
{
if (f[i] == 0 || v[f[i]]) //要么没有先决条件,要么已经被攻占了
{
sum += a[i];
cnt++;
}
}
}
if (cnt == m)
return sum;
else
return 0;
}
void dfs(int x, int c)
{
if (c == m)
{
ans = max(ans, find());
return;
}
if (x == n + 1)
return;
v[x] = 1;
dfs(x + 1, c + 1);
v[x] = 0;
dfs(x + 1, c);
}
int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
if (n == 0 && m == 0)
break;
for (int i = 1; i <= n; i++)
scanf("%d%d", f[i], a[i]);
ans = 0;
memset(v, 0, sizeof(v));
dfs(0, 0);
printf("%d\n", ans);
}
return 0;
}
BFS
BFS本质就是让你从一幅[图]中找到从起点
start
到终点target
的最近距离。
BFS模板:
int minDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
// root 本身就是一层,depth 初始化为 1
int depth = 1;
while (!q.isEmpty()) {
int sz = q.size();
/* 将当前队列中的所有节点向四周扩散 */
for (int i = 0; i < sz; i++) {
TreeNode cur = q.poll();
/* 判断是否到达终点 */
if (cur.left == null && cur.right == null)
return depth;
/* 将 cur 的相邻节点加入队列 */
if (cur.left != null)
q.offer(cur.left);
if (cur.right != null)
q.offer(cur.right);
}
/* 这里增加步数 */
depth++;
}
return depth;
}
- 走迷宫(求最少步数)
#include <stdio.h>
#include <stdlib.h>
char maze[10][10] = {"000S0", "0XXX0", "00000", "0XXX0", "0000E"};
int sum = 0;
typedef struct mazeNode
{
int x, y;
int step;
} node;
node Queue[1000]; //初始化一个队列
/*
can()函数功能:用来判断该点是否在区域内
*/
int can(int x, int y)
{
if (maze[x][y] == 'X')
return 0;
if (x != -1 && x != 5 && y != -1 && y != 5)
return 1;
else
return 0;
}
int main()
{
/*找起始点和终点*/
int stx, sty;
int enx, eny;
int dx[4] = {-1, 0, 1, 0}; //方向数组
int dy[4] = {0, -1, 0, 1};
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
if (maze[i][j] == 'S')
{
stx = i;
sty = j;
}
if (maze[i][j] == 'E')
{
enx = i;
sty = j;
}
}
} //for
/*查找结束*/
int rear = 0;
int front = 0;
node p = {stx, sty, 0}; //初始化
Queue[rear++] = p;
while (front < rear)
{
p = Queue[front++];
if (p.x == enx && p.y == eny)
{
printf("the min step: %d\n", p.step);
break;
}
for (int i = 0; i < 4; i++)
{
int px = p.x + dx[i];
int py = p.y + dy[i];
if (can(px, py))
{
p.step = p.step + 1;
p.x = px;
p.y = py;
Queue[rear++] = p;
}
}
}
return 0;
}