# 《啊哈！算法》－第 4 章：万能的搜索

_我已经从中二毕业了

## 深度优先搜索

``````void dfs(int step) {
// 判断边界
// 尝试每一种可能
for (i = 1; i <= n; i++) {
// 继续下一步
dfs(step + 1);
}
// 返回
}``````

## 使用深度优先搜索解决问题

### [][][] + [][][] = [][][] 问题

``````#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;
}``````

### 解救小哈

``````int a[4][4] = {
{0, 0, 2, 0},
{0, 0, 0, 2},
{0, 2, 0, 0},
{0, 0, 0, 0}
};``````

``````#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];
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;
}
}
}
}

// 每一个点尝试完毕后，需要出队
}

printf("(%d, %d) %d\n", p, q, max);

return 0;
}``````

7.9k 声望
235 粉丝
0 条评论