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


    算法背景

    迷宫问题和棋盘马走日问题都是搜索问题(找路径),一般采用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是清明的茗
  • 相关阅读:
    刻意练习:从一般到卓越的方法
    Spring JMS 整合 ActiveMQ
    冒泡排序 快速排序
    TCP协议,UDP 协议的区别
    HashMap实现原理
    java 类加载过程
    Linux-vim命令(3)
    Linux-vim命令(2)
    Linux-vim命令(1)
    Linux-命令里的快捷键
  • 原文地址:https://www.cnblogs.com/MinPage/p/13951691.html
Copyright © 2020-2023  润新知