图的搜索算法之迷宫问题和棋盘马走日问题

算法背景

迷宫问题和棋盘马走日问题都是搜索问题(找路径),一般采用DFS和BFS两种搜索算法都可以,如果要求是最短路径,则一般BFS解题,DFS则需要记录所有的可能路径,找到最短的那条。一般来说,迷宫问题的前进方向为四个(上下左右),障碍物直接用1和0来判断。而马走日则有特殊的障碍物判断规则,前进方向也扩展为了八个(上下左右和四个斜角)。下面就用算法实例来讲解这类问题的一般解法。

迷宫问题(带障碍物)

例题一:(求通路)

输入:一个二维矩阵,表示迷宫(0表示通道,1表示围墙)。

maze = {
    {1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    {1,1,1,1,1,1,1,1,1,1}
 }

输出:一条走出迷宫的路径。

解题方法有两种:栈和队列。

栈(DFS)

解题思路

  • 在一个迷宫节点(x,y)上,可以进行四个方向的探查:maze[x-1][y], maze[x+1][y], maze[x][y-1], maze[x][y+1]
  • 思路:从一个节点开始,任意找下一个能走的点,当找不到能走的点时,退回上一个点寻找是否有其他方向的点。
  • 方法:创建一个空栈,首先将入口位置进栈。当栈不空时循环:获取栈顶元素,寻找下一个可走的相邻方块,如果找不到可走的相邻方块,说明当前位置是死胡同,进行回溯(就是讲当前位置出栈,看前面的点是否还有别的出路)

代码实现(C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
    int x, y;
} Node;

typedef struct Stack {
    Node **data;
    int top_index, length;
} Stack;

int direct[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

int maze[10][10] = {
        {1,1,1,1,1,1,1,1,1,1},
        {1,0,0,1,0,0,0,1,0,1},
        {1,0,0,1,0,0,0,1,0,1},
        {1,0,0,0,0,1,1,0,0,1},
        {1,0,1,1,1,0,0,0,0,1},
        {1,0,0,0,1,0,0,0,0,1},
        {1,0,1,0,0,0,1,0,0,1},
        {1,0,1,1,1,0,1,1,0,1},
        {1,1,0,0,0,0,0,0,0,1},
        {1,1,1,1,1,1,1,1,1,1}
     };

void init_node(Node *node, int x, int y) {
    node->x = x;
    node->y = y;
    return;
}

void init_stack(Stack *s, int size) {
    s->length = size;
    s->data = (Node **)malloc(sizeof(Node *) * size);
    s->top_index  = -1;
    return;
}

void push(Stack *s, Node *node) {
    if (s->top_index >= s->length) {
        return;
    }
    s->top_index++;
    s->data[s->top_index] = node;
    return;
}
int empty(Stack *s) {
    if (s->top_index < 0) {
        return 1;
    } else {
        return 0;
    }
}

Node *top(Stack *s) {
    return s->data[s->top_index];
}

void pop(Stack *s) {
    if (empty(s)) {
        return;
    } else {
        s->top_index--;
        return;
    }
}

void clear_stack(Stack *s) {
    free(s->data);
    free(s);
}
void output(Stack *s) {
    for (int i =0; i <= s->top_index; ++i) {
        i == 0 || printf("=>");
        printf("(%d, %d)", s->data[i]->x, s->data[i]->y);
    }
    printf("
");
    return;
}

int check(int x, int y) {
    if (x >=0 && x < 10 && y >=0 && y < 10) {
        return 1;
    } else {
        return 0;
    }
}

void solve_maze(int x0, int y0, int x1, int y1) {
    Stack *s = (Stack *)malloc(sizeof(Stack));
    init_stack(s, 100);
    Node *start_node = (Node *)malloc(sizeof(Node));
    init_node(start_node, x0, y0);
    push(s, start_node);
    maze[x0][x1] = -1;
    int flag;
    while (!empty(s)) {
        Node *cur_node = top(s);
        flag = 0;
        if (cur_node->x == x1 && cur_node->y == y1) {
            output(s);
            printf("Success!
");
            return;
        }
        for (int i = 0; i < 4; i++) {
            if (check(cur_node->x + direct[0][i], cur_node->y + direct[1][i]) && maze[cur_node->x + direct[0][i]][cur_node->y + direct[1][i]] == 0) {
                Node *tmp = (Node *)malloc(sizeof(Node));
                init_node(tmp,cur_node->x + direct[0][i], cur_node->y + direct[1][i]);
                push(s, tmp);
                maze[cur_node->x + direct[0][i]][cur_node->y + direct[1][i]] = -1;
                output(s);
                flag = 1;
                break;
            }
        }
        if (flag == 0) {
            pop(s);
        }
    }
    printf("Failed!
");
    return;
}
int main() {
    int x0, y0, x1, y1;
    scanf("%d%d%d%d", &x0, &y0, &x1, &y1);
    solve_maze(x0, y0, x1, y1);
    return 0;
}

最后生成的是深度优先搜索树,每个结点只访问一次,注意在入栈时要将maze的信息置为-1,表示已访问,不然会陷入死循环!!

队列(BFS)

解题思路

  • 思路:从一个节点开始,寻找所有下面能继续走的点。继续寻找,直到找到出口。
  • 方法:创建一个空队列,将起点位置进队。在队列不为空时循环:出队一次。如果当前位置为出口,则结束算法;否则找出当前方块的4个相邻方块中可走的方块,全部进队。

代码实现(C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
    int x, y, pre;
} Node;

typedef struct Queue {
    Node **data;
    int head, tail, length;
} Queue;

int direct[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

int maze[10][10] = {
        {1,1,1,1,1,1,1,1,1,1},
        {1,0,0,1,0,0,0,1,0,1},
        {1,0,0,1,0,0,0,1,0,1},
        {1,0,0,0,0,1,1,0,0,1},
        {1,0,1,1,1,0,0,0,0,1},
        {1,0,0,0,1,0,0,0,0,1},
        {1,0,1,0,0,0,1,0,0,1},
        {1,0,1,1,1,0,1,1,0,1},
        {1,1,0,0,0,0,0,0,0,1},
        {1,1,1,1,1,1,1,1,1,1}
     };


void init_node(Node *node, int x, int y, int pre) {
    node->x = x;
    node->y = y;
    node->pre = pre;
    return;
}

void init_queue(Queue *q, int size) {
    q->length = size;
    q->data = (Node **)malloc(sizeof(Node *) * size);
    q->head = 0;
    q->tail  = -1;
    return;
}

void push(Queue *q, Node *node) {
    if (q->tail + 1 >= q->length) {
        return;
    }
    q->tail++;
    q->data[q->tail] = node;
    return;
}

int empty(Queue *q) {
    if (q->head > q->tail) {
        return 1;
    } else {
        return 0;
    }
}

Node *front(Queue *q) {
    return q->data[q->head];
}

void pop(Queue *q) {
    if (empty(q)) {
        return;
    } else {
        q->head++;
        return;
    }
}

void clear_queue(Queue *q) {
    free(q->data);
    free(q);
}

void output(Queue *q) {
    if (empty(q)) {
        return;
    } else {
        Queue *output = (Queue *)malloc(sizeof(Queue));
        init_queue(output, 100);
        for (Node *node = q->data[q->tail]; node != q->data[q->head]; node = q->data[node->pre]) {
            push(output, node);
        }
        push(output, q->data[q->head]); //不要遗漏!
        for (int i  = output->tail; i >= output->head; --i) {
            i  == output->tail || printf("=>");
            printf("%d (%d, %d)", output->data[i]->pre, output->data[i]->x, output->data[i]->y);
        }
        printf("
");
        return;
    }

}

int check(int x, int y) {
    if (x >=0 && x < 10 && y >=0 && y < 10) {
        return 1;
    } else {
        return 0;
    }
}

void solve_maze(int x0, int y0, int x1, int y1) {
    Queue *q = (Queue *)malloc(sizeof(Queue));
    Queue *path = (Queue *)malloc(sizeof(Queue));
    init_queue(q, 100);
    init_queue(path, 100);
    Node *start_node = (Node *)malloc(sizeof(Node));
    init_node(start_node, x0, y0, -1);
    push(q, start_node);
    maze[x0][x1] = -1;
    int id = -1;
    while (!empty(q)) {
        Node *cur_node = front(q);
        push(path, cur_node);
        pop(q);
        id++;
        if (cur_node->x == x1 && cur_node->y == y1) {
            output(path);
            printf("Success!
");
            return;
        }
        for (int i = 0; i < 4; i++) {
            if (check(cur_node->x + direct[0][i], cur_node->y + direct[1][i]) && maze[cur_node->x + direct[0][i]][cur_node->y + direct[1][i]] == 0) {
                Node *tmp = (Node *)malloc(sizeof(Node));
                init_node(tmp, cur_node->x + direct[0][i], cur_node->y + direct[1][i], id);
                push(q, tmp);
                maze[cur_node->x + direct[0][i]][cur_node->y + direct[1][i]] = -1;
            }
        }

    }
    printf("Failed!
");
    return;
}

int main() {
    int x0, y0, x1, y1;
    scanf("%d%d%d%d", &x0, &y0, &x1, &y1);
    solve_maze(x0, y0, x1, y1);
    return 0;
}

【易错点记录】

  1. 赋值“=”与等于“==”不要弄混了;
  2. 注意for循环中间的不是停止条件而是继续条件!!!
  3. 结构体的初始化操作不要忘记!
  4. 多检查和对停止与边界条件!尤其是开头和和结尾的结点不要在条件判断后遗漏了!!

例题二(求走法)

例题一是最简单的带障碍物迷宫问题,下面增加限制条件:每个位置只能访问一次,求一种有多少种走法。

一般不求最短路径,只统计走法数,我们采用DFS递归的形式来解题。

代码实现(C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int **maze;
int direct[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
int count = 0;
int **visited;

int check(int x, int y) {
    if (x >=0 && x < 10 && y >=0 && y < 10) {
        return 1;
    } else {
        return 0;
    }
}

void output(int n, int m) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            j == 0 || printf(" ");
            printf("%d", maze[i][j]);
        }
        printf("
");
    }
}

void dfs(int x0, int y0, int x1, int y1) {
    if (x0 == x1 && y0 == y1) {
        count++;
        printf("
");
        return;
    }
    for (int i = 0; i < 4; i++) {
        int newx = x0 +direct[i][0];
        int newy = y0 +direct[i][1];
        if (check(newx, newy) && maze[newx][newy] == 0 && visited[newx][newy] == 0) {
            visited[newx][newy] = 1;
            printf("=>(%d, %d)", newx, newy);
            dfs(newx, newy, x1, y1);
            visited[newx][newy] = 0;
        }
    }
}

/*测试用例
5 5 8
0 0 4 4
1 1
1 2
1 3
2 1
2 3
3 1
3 3
3 2
 */
int main() {
    int n, m, t;
    scanf("%d%d%d", &n, &m, &t);
    int x0, y0, x1, y1;
    scanf("%d%d%d%d", &x0, &y0, &x1, &y1);
    maze = (int **)malloc(sizeof(int *) * n);
    visited = (int **)malloc(sizeof(int *) * n);
    for (int  i = 0; i < n; i++) {
        maze[i] = (int *)malloc(sizeof(int) * m);
        visited[i] = (int *)malloc(sizeof(int) * m);
        memset(maze[i], 0 ,sizeof(int) * m);
        memset(visited[i], 0 ,sizeof(int) * m);
    }
    int x, y;
    for (int i = 0; i < t; i++) {
        scanf("%d%d", &x, &y);
        maze[x][y] = 1;
    }
    output(n, m);
    if (!check(x0, y0) || !check(x1, y1)) {
            printf("ERROR!
");
    } else {
        printf("(%d, %d): 
", x0, y0);
        visited[x0][y0] = 1;
        dfs(x0, y0, x1, y1);        printf("%d
", count);
    }
    return 0;
}
/*输出
0 0 0 0 0
0 1 1 1 0
0 1 0 1 0
0 1 1 1 0
0 0 0 0 0
(0, 0): 
=>(1, 0)=>(2, 0)=>(3, 0)=>(4, 0)=>(4, 1)=>(4, 2)=>(4, 3)=>(4, 4)

=>(0, 1)=>(0, 2)=>(0, 3)=>(0, 4)=>(1, 4)=>(2, 4)=>(3, 4)=>(4, 4)
2*/

【易错点记录】

memset函数的二维数组初始化:

  • 声明二维数组a[n][n],则可以用memset(a,0x3f,sizeof(a))。因为声明的二维数组存储单元是连续的。
  • 但是动态声明的二维数组指针int **q只能够每次获取q[i]后对每行进行初始化,因为指针对于每行的存储单元不连续。

棋盘马走日问题

无障碍

例题一:(遍历)

输入:国际象棋的棋盘是$8 x 8$的方格(按顺序编号1~64)。现在给定马的起始位置,遍历整个棋盘,要求每个方格有且仅访问一次。

输出:遍历路径(编号序列)。

解题思路

dfs递归遍历,用栈存储路径,起点任意(不一定有解)。

代码实现(C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int direct[8][2] = {{1, 2}, {2, 1}, {-1, -2}, {-2, -1}, {1, -2}, {2, -1}, {-1, 2}, {-2, 1}};
int **maze;
int **visited;

typedef struct Stack {
    int *id;
    int top_index, length;
} Stack;

void init_stack(Stack *s, int size) {
    s->length = size;
    s->id = (int * )malloc(sizeof(int) * size);
    s->top_index = -1;
    return;
}

void push(Stack *s, int id) {
    if (s->top_index + 1 >= s->length) {
        return;
    }
    s->top_index++;
    s->id[s->top_index] = id;
}

int empty(Stack *s) {
    if (s->top_index < 0) {
        return 1;
    } else {
        return 0;
    }
}

int top(Stack *s) {
    return s->id[s->top_index];
}

void pop(Stack *s) {
    if (empty(s)) {
        return;
    } else {
        s->top_index--;
        return;
    }
}

void clear(Stack *s) {
    free(s->id);
    free(s);
    return;
}

int check(int x, int y) {
    if (x < 0 || y < 0 || x >= 8 || y >= 8 ) {
        return 0;
    } else {
        return 1;
    }
}

void output(Stack *s) {
    for (int i = 0; i < s->top_index; i++) {
        i == 0 || printf("=>");
        printf("%d", s->id[i]);
    }
    printf("
");
    return;
}

void output_maze() {
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            j == 0 || printf(" ");
            printf("%d", maze[i][j]);
        }
        printf("
");
    }
    return;
}

Stack *path;
int flag;

void bianli_dfs(int x, int y) {
    visited[x][y] = 1;
    push(path, maze[x][y]);
    output(path);
    while (!empty(path)) {
        if (path->top_index == 63) {
            printf("Find!
");
            output(path);
            flag = 1;
            return;
        }
        int id = top(path);
        int cur_x = id / 8;
        int cur_y = id % 8;
        int newx, newy;
        for (int i = 0; i < 8; i++) {
            newx = cur_x + direct[i][0];
            newy = cur_y + direct[i][1];
            if (check(newx, newy) && visited[newx][newy] == 0) {
                bianli_dfs(newx, newy);
                if (flag ==1) {
                    return;
                }
            }
        }
        pop(path);
        visited[cur_x][cur_y] = 0;
    }
    return;
}

void free_mat(int **mat) {
    for (int i = 0; i < 8; i++) {
        free(mat[i]);
    }
    free(mat);
}

int main() {
    maze = (int **)malloc(sizeof(int *) * 8);
    visited = (int **)malloc(sizeof(int *) * 8);
    int id = 1;
    for (int i = 0; i < 8; i++) {
        maze[i] = (int *)malloc(sizeof(int) * 8);
        visited[i] = (int *)malloc(sizeof(int) * 8);
        memset(visited[i], 0 ,sizeof(int) * 8);
        for (int j = 0; j < 8; j++) {
            maze[i][j] = id++;
        }
    }
    //output_maze();
    int x, y;
    printf("Please enter the start coordinate: (x, y)
");
    fflush(stdout);
    scanf("(%d, %d)", &x, &y);
    if (!check(x, y)) {
        printf("ERROR
");
    } else {
        path = (Stack *)malloc(sizeof(Stack));
        init_stack(path, 64);
        bianli_dfs(x, y);
    }
    free_mat(maze);
    free_mat(visited);
    return 0;
}

例题二:(求最短路径)

题目描述

在国际象棋中,马的走法与中国象棋类似,即俗话说的“马走日”,下图所示即国际象棋中马每一步能到达的格子(箭头所指为每步到达位置)。现有一200 * 200大小的国际象棋棋盘,棋盘中仅有一个马,给定马的当前位置和目标位置,求出马最少需要多少跳才能从当前位置到达目标位置。

输入格式:已有文件txt格式文件里每一行有四个以空格分隔的整数,分别表示马当前位置及目标位置的横、纵坐标(Xs,Ys)和(Xe,Ye)。坐标由0开始。

文件输入样例:

1 1 2 1

1 5 5 1

输入说明第一行:马的当前位置为(1,1),目标位置为(2,1)。第二行:马的当前位置为(1,5),目标位置为(5,1)。

输出:文件里每一行第一个数字为1个整数,即马从当前位置跳到目标位置最少的跳数,然后以空格隔开,输出对应的最短路径坐标,坐标格式为(X, Y),每个坐标之间以空格隔开。所有路径输出后以回车换行。

输出样例:

3 (1, 1) (3, 2) (4, 0) (2, 1)

4 (1, 5) (2, 3) (4, 2) (6, 3) (5, 1)

第一行:马需要跳3次才可以从(1,1)到(2,1),对应的路径为(1, 1) (3, 2) (4, 0) (2, 1)。第二行:马需要跳4次才可以从(1,5)到(5,1),对应的路径为(1, 5) (2, 3) (4, 2) (6, 3) (5, 1)。

解题思路

队列bfs循环,注意最后输出路径的顺序,不要遗漏起点!

代码实现(C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 200
#define M 200

int direct[8][2] = {{1, 2}, {2, 1}, {-1, -2}, {-2, -1}, {1, -2}, {2, -1}, {-1, 2}, {-2, 1}};
int **maze;

typedef struct Node {
    int x, y, pre;
} Node;

Node *create_node(int x, int y, int pre) {
    Node *node = (Node *)malloc(sizeof(Node));
    node->x = x;
    node->y = y;
    node->pre = pre;
    return node;
}

typedef struct Queue {
    Node **data;
    int head, tail, length;
} Stack;

void init_queue(Queue *q, int size) {
    q->length = size;
    q->data = (Node **)malloc(sizeof(Node *) * size);
    q->tail = -1;
    q->head = 0;
    return;
}

void push(Queue *q, Node *node){
    if (q->tail + 1 >= q->length) {
        return;
    }
    q->tail++;
    q->data[q->tail] = node;
    return;
}
int empty(Queue *q) {
    if (q->head > q->tail) {
        return 1;
    } else {
        return 0;
    }
}

Node *front(Queue *q) {
    if (!empty(q)) {
        return q->data[q->head];
    }
    return NULL;
}

void pop(Queue *q) {
    if (!empty(q)) {
        q->head++;
    }
}

void clear_queue(Queue *q) {
    free(q->data);
    free(q);
    return;
}

int check(int x, int y) {
    if (x < 0 || y < 0 || x >= N || y >= M ) {
        return 0;
    } else {
        return 1;
    }
}


void output(Queue *q) {
    int count = 0;
    Queue *res = (Queue *)malloc(sizeof(Queue));
    init_queue(res, N * M);
    for (Node *node = q->data[q->tail]; node != q->data[q->head]; node = q->data[node->pre]) {
        count++;
        push(res, node);
    }
    push(res, q->data[q->head]);
    printf("%d ", count);
    for (int i = res->tail; i >= res->head; i-- ) {
            printf("(%d, %d) ", res->data[i]->x,  res->data[i]->y);
    }
    return;
}

void output_maze() {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            j == 0 || printf(" ");
            printf("%d", maze[i][j]);
        }
        printf("
");
    }
    return;
}void bfs(int sx, int sy, int ex, int ey) {
    Queue *q = (Queue *)malloc(sizeof(Queue));
    init_queue(q, N *M);
    Queue *path = (Queue *)malloc(sizeof(Queue));
    init_queue(path, N *M);
    int pre = -1;
    Node *start_node = create_node(sx, sy, pre);
    push(q, start_node);
    maze[sx][sy] = 1;
    while (!empty(q)) {
        Node *cur_node = front(q);
        pop(q);
        push(path, cur_node);
        //output(path);
        ++pre;
        if (cur_node->x == ex && cur_node->y == ey) {
            output(path);
            free(path);
            free(q);
            return;
        }
        for (int i = 0; i < 8; i++) {
            int newx = cur_node->x + direct[i][0];
            int newy = cur_node->y + direct[i][1];
            if (check(newx, newy) && maze[newx][newy] == 0) {
                Node *new_node = create_node(newx, newy, pre);
                maze[newx][newy] = 1;
                push(q, new_node);
            }
        }
    }
    return;
}

void free_mat(int **mat) {
    for (int i = 0; i < 8; i++) {
        free(mat[i]);
    }
    free(mat);
}

int main() {
    maze = (int **)malloc(sizeof(int *) * N);
    for (int i = 0; i < N; i++) {
        maze[i] = (int *)malloc(sizeof(int) * M);
        memset(maze[i], 0 ,sizeof(int) * M);
    }
    //output_maze();
    int sx, sy, ex, ey;
    scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
    if (!check(sx, sy) || !check(ex, ey)) {
        printf("ERROR
");
    } else {
        bfs(sx, sy, ex, ey);
    }
    free_mat(maze);
    return 0;
}

例题三:(求走法)

解题思路

一般统计走法推荐dfs递归,实现简单快捷。

代码实现(C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int direct[8][2] = {{1, 2}, {2, 1}, {-1, -2}, {-2, -1}, {1, -2}, {2, -1}, {-1, 2}, {-2, 1}};
int **maze;
int n, m;
int count = 0;
int len = 1;

typedef struct Node {
    int x, y, pre;
} Node;

Node *create_node(int x, int y, int pre) {
    Node *node = (Node *)malloc(sizeof(Node));
    node->x = x;
    node->y = y;
    node->pre = pre;
    return node;
}

int check(int x, int y) {
    if (x < 0 || y < 0 || x >= n || y >= n ) {
        return 0;
    } else {
        return 1;
    }
}


void output_maze() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            j == 0 || printf(" ");
            printf("%d", maze[i][j]);
        }
        printf("
");
    }
    return;
}


void dfs_count(int x, int y) {
    if (len == n * m) {
        count++;
    }
    for (int i = 0; i < 8; i++) {
        int newx = x + direct[i][0];
        int newy = y + direct[i][1];
        if (check(newx, newy) && maze[newx][newy] == 0) {
            maze[newx][newy] = 1;
            len++;
            dfs_count(newx, newy);
            len--;
            maze[newx][newy] = 0;
        }
    }
    return;
}

void free_mat(int **mat) {
    for (int i = 0; i < 8; i++) {
        free(mat[i]);
    }
    free(mat);
}

int main() {
    int t, sx, sy;
    scanf("%d", &t);
    for (int i = 0; i < t; i++) {
        scanf("%d%d%d%d", &n, &m, &sx, &sy);
        if (n == 1 && m == 1) {
            printf("1
");
            break;
        }
        if (!check(sx, sy)) {
            printf("ERROR
");
        } else {
            maze = (int **)malloc(sizeof(int *) * n);
            for (int i = 0; i < n; i++) {
                maze[i] = (int *)malloc(sizeof(int) * m);
                memset(maze[i], 0 ,sizeof(int) * m);
            }
            maze[sx][sy] = 1;
            dfs_count(sx, sy);
            printf("%d
", count);
            free_mat(maze);
            count = 0;
        }
    }
    return 0;
}

带障碍物

骑马走江湖

 别马脚:

参考资料:

https://www.cnblogs.com/huchong/p/8522453.html

https://www.it610.com/article/1295331529966297088.htm

https://blog.csdn.net/weixin_43564373/article/details/84101191

https://blog.csdn.net/fun_always/article/details/90115780

https://blog.csdn.net/fun_always/article/details/90115780

Min是清明的茗
原文地址:https://www.cnblogs.com/MinPage/p/13951691.html