深度优先搜索
深度优先搜索(Depth First Search, DFS)。理解深度优先搜索的关键在于解决“当下该如何做”。至于“下一步该如何做”则与“当下该如何做”是一样的。下面的代码就是深度优先搜索的基本模型:
void dfs(int step) {
// 判断边界
// 尝试每一种可能
for (i = 1; i <= n; i++) {
// 继续下一步
dfs(step + 1);
}
// 返回
}
发明深度优先算法的是 John E. Hopcroft(约翰·霍普克洛特)和 Robert E. Tarjan(罗伯特·陶尔扬)。
使用深度优先搜索解决问题
[][][] + [][][] = [][][] 问题
#include <stdio.h>
#define NUM 10
int a[NUM], book[NUM];
void dfs(int step) {
int i;
if (step == 10) {
if (
(a[1] * 100 + a[2] * 10 + a[3]) + (a[4] * 100 + a[5] * 10 + a[6]) == a[7] * 100 + a[8] * 10 + a[9]
) {
for (i = 1; i <= 9; i++) {
printf("%d", a[i]);
}
printf("\n");
}
}
for (i = 1; i <= 9; i++) {
if (book[i] == 0) {
a[step] = i;
book[i] = 1;
dfs(step + 1);
book[i] = 0;
}
}
}
int main(void) {
dfs(1);
return 0;
}
全排列
#include <stdio.h>
#define NUM 10
int a[NUM], book[NUM], n;
void dfs(int step) {
int i;
if (step == n + 1) {
for (i = 1; i <= n; i++) {
printf("%d", a[i]);
}
printf("\n");
return;
}
for (i = 1; i <= n; i++) {
if (book[i] == 0) {
a[step] = i;
book[i] = 1;
dfs(step + 1);
book[i] = 0;
}
}
}
int main(void) {
scanf("%d", &n);
dfs(1);
return 0;
}
解救小哈
方向感不好的小哈在迷宫里迷路了。小哼得知后便立即去解救小哈。假如小哼已经知道迷宫的地图和小哈的位置,且迷宫中有障碍物,小哼是不能够到达的。那么求出小哼怎样走能够最快的找到小哈?
地图由一个二维数组组成,用 0 表示可到达的位置,2 表示不可到达的位置:
int a[4][4] = {
{0, 0, 2, 0},
{0, 0, 0, 2},
{0, 2, 0, 0},
{0, 0, 0, 0}
};
得知小哈的位置在(2, 2)
。
#include <stdio.h>
int a[4][4] = {
{0, 0, 2, 0},
{0, 0, 0, 2},
{0, 2, 0, 0},
{0, 0, 0, 0}
};
int book[4][4], tx, ty, min = 9999;
int forward[4][2] = {
{-1, 0},
{0, 1},
{1, 0},
{0, -1}
};
void dfs(int x, int y, int step) {
int i;
// 边界
if (x == 2 && y == 2) {
if (step < min) {
min = step;
}
// 返回
return;
}
// 尝试每一种可能
for (i = 0; i < 4; i++) {
tx = x + forward[i][0];
ty = y + forward[i][1];
if (tx >= 0 || tx < 4 || ty >=0 || ty < 4) {
if (a[tx][ty] == 0 && book[tx][ty] == 0) {
book[tx][ty] = 1;
// 继续下一步
dfs(tx, ty, step + 1);
book[tx][ty] = 0;
}
}
}
}
int main(void) {
int i, j;
for (i = 0; i < 4; i++)
for(j = 0; j < 4; j++)
book[i][j] = 0;
book[0][0] = 1;
dfs(0, 0, 0);
printf("%d\n", min);
return 0;
}
炸弹人
#include <stdio.h>
#define NUM 13
char a[NUM][NUM] = {
{'#','#','#','#','#','#','#','#','#','#','#','#','#'},
{'#','G','G','.','G','G','G','#','G','G','G','.','#'},
{'#','#','#','.','#','G','#','G','#','G','#','G','#'},
{'#','.','.','.','.','.','.','.','#','.','.','G','#'},
{'#','G','#','.','#','#','#','.','#','G','#','G','#'},
{'#','G','G','.','G','G','G','.','#','.','G','G','#'},
{'#','G','#','.','#','G','#','.','#','.','#','.','#'},
{'#','#','G','.','.','.','G','.','.','.','.','.','#'},
{'#','G','#','.','#','G','#','#','#','.','#','G','#'},
{'#','.','.','.','G','#','G','G','G','.','G','G','#'},
{'#','G','#','.','#','G','#','G','#','.','#','G','#'},
{'#','G','G','.','G','G','G','#','G','.','G','G','#'},
{'#','#','#','#','#','#','#','#','#','#','#','#','#'}
};
int book[NUM][NUM];
int max = 0, amount, p, q;
int direction[4][2] = {
{-1, 0},
{0, 1},
{1, 0},
{0, -1}
};
int getNum(int i, int j) {
// 杀上边的怪
int x = i;
int y = j;
int num = 0;
while (a[x][y] != '#') {
if (a[x][y] == 'G') {
num += 1;
}
x -= 1;
}
// 杀右边的怪
x = i;
y = j;
while (a[x][y] != '#') {
if (a[x][y] == 'G') {
num += 1;
}
y += 1;
}
// 杀下边的怪
x = i;
y = j;
while (a[x][y] != '#') {
if (a[x][y] == 'G') {
num += 1;
}
x += 1;
}
// 杀左边的怪
x = i;
y = j;
while (a[x][y] != '#') {
if (a[x][y] == 'G') {
num += 1;
}
y -= 1;
}
return num;
}
void dfs(int x, int y) {
int i;
// 边界判断
amount = getNum(x, y);
if (amount > max) {
max = amount;
p = x;
q = y;
}
// 尝试每一步
for (i = 0; i < 4; i++) {
int tx = x + direction[i][0];
int ty = y + direction[i][1];
if (tx > 1 || tx < NUM || ty > 1 || ty < NUM) {
if (a[tx][ty] == '.' && book[tx][ty] == 0) {
book[tx][ty] = 1;
// 尝试下一步
dfs(tx, ty);
}
}
}
}
int main(void) {
book[3][3] = 1;
dfs(3, 3);
printf("(%d, %d) %d\n", p, q, max);
return 0;
}
使用广度优先搜索解决问题
炸弹人
#include <stdio.h>
#define NUM 13
char a[NUM][NUM] = {
{'#','#','#','#','#','#','#','#','#','#','#','#','#'},
{'#','G','G','.','G','G','G','#','G','G','G','.','#'},
{'#','#','#','.','#','G','#','G','#','G','#','G','#'},
{'#','.','.','.','.','.','.','.','#','.','.','G','#'},
{'#','G','#','.','#','#','#','.','#','G','#','G','#'},
{'#','G','G','.','G','G','G','.','#','.','G','G','#'},
{'#','G','#','.','#','G','#','.','#','.','#','.','#'},
{'#','#','G','.','.','.','G','.','.','.','.','.','#'},
{'#','G','#','.','#','G','#','#','#','.','#','G','#'},
{'#','.','.','.','G','#','G','G','G','.','G','G','#'},
{'#','G','#','.','#','G','#','G','#','.','#','G','#'},
{'#','G','G','.','G','G','G','#','G','.','G','G','#'},
{'#','#','#','#','#','#','#','#','#','#','#','#','#'}
};
int book[NUM][NUM];
int max = 0;
int direction[4][2] = {
{-1, 0},
{0, 1},
{1, 0},
{0, -1}
};
int getNum(int i, int j) {
// 杀上边的怪
int x = i;
int y = j;
int num = 0;
while (a[x][y] != '#') {
if (a[x][y] == 'G') {
num += 1;
}
x -= 1;
}
// 杀右边的怪
x = i;
y = j;
while (a[x][y] != '#') {
if (a[x][y] == 'G') {
num += 1;
}
y += 1;
}
// 杀下边的怪
x = i;
y = j;
while (a[x][y] != '#') {
if (a[x][y] == 'G') {
num += 1;
}
x += 1;
}
// 杀左边的怪
x = i;
y = j;
while (a[x][y] != '#') {
if (a[x][y] == 'G') {
num += 1;
}
y -= 1;
}
return num;
}
int main(void) {
int i, j, tx, ty, amount, p, q;
for (i = 0; i < NUM; i++)
for (j = 0; j < NUM; j++)
book[i][j] = 0;
// 初始化队列
struct node {
int x;
int y;
} que[1000];
int head, tail;
head = 0;
tail = 0;
// 设定?人的位置
book[3][3] = 1;
que[tail].x = 3;
que[tail].y = 3;
tail++;
// 广度优先搜索模型
while (head < tail) {
for (i = 0; i < 4; i++) {
tx = que[head].x + direction[i][0];
ty = que[head].y + direction[i][1];
// 判断是否跑出地图外
if (tx > 1 || tx < NUM || ty > 1 || ty < NUM) {
// 判断该位置是否可用到达
if (a[tx][ty] == '.' && book[tx][ty] == 0) {
que[tail].x = tx;
que[tail].y = ty;
book[tx][ty] = 1;
tail++;
// 计算杀敌数量
amount = getNum(tx, ty);
if (amount > max) {
max = amount;
p = tx;
q = ty;
}
}
}
}
// 每一个点尝试完毕后,需要出队
head++;
}
printf("(%d, %d) %d\n", p, q, max);
return 0;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。