迷宫走最短路径含体力值设定

这篇文章介绍了如何使用栈和递归来解决牛客网上的一道编程题目,涉及迷宫路径搜索,通过维护一个路径栈来寻找从入口到出口的最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


 

牛客网题目链接:地下迷宫_牛客题霸_牛客网 (nowcoder.com)

#include <stdio.h>

#include <stdbool.h>

#include <assert.h>

#include <malloc.h>

#include <stdlib.h>

#include <string.h>

typedef struct Postion {

    int row;

    int col;

} PT;

typedef PT STDataType;


 

///

typedef struct Stack {

    STDataType* a;

    int top;

    int capacity;//容量

} ST;



 

ST path;//创建路径

ST minpath;//最短路径

//初始化

void StackInit(ST* ps) {

    assert(ps);

    ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);

    if (ps->a == NULL) {

        printf("realloc fail\n");

        exit(-1);

    } else {

        ps->capacity = 4;

        ps->top = 0;

    }

}

//销毁

void StackDestory(ST* ps) {

    assert(ps);

    free(ps->a);

    ps->a = NULL;

    ps->top = ps->capacity = 0;

}

//入数据

void StackPush(ST* ps, STDataType x) {

    assert(ps);

    //数据满了

    if (ps->top == ps->capacity) {

        STDataType* tmp = (STDataType*)realloc(ps->a,

                                               ps->capacity * 2 * sizeof(STDataType));

        if (tmp == NULL) {

            printf("realloc fail\n");

            exit(-1);

        } else {

            ps->a = tmp;

            ps->capacity *= 2;

        }

    }

    ps->a[ps->top] = x;

    ps->top++;

}

//出数据

void StackPop(ST* ps) {

    assert(ps);

    //栈空了调用pop报错

    assert(ps->top > 0);

    ps->top--;

}

//查看栈顶元素

STDataType StackTop(ST* ps) {

    assert(ps);

    //栈空了调用查看报错

    assert(ps->top > 0);

    return ps->a[ps->top - 1];

}

//查看栈大小

int StackSize(ST* ps) {

    assert(ps);

    return ps->top;

}

//判断是否为空

bool StackEmpty(ST* ps) {

    assert(ps);

    return ps->top == 0;

}

/


 

//打印迷宫

void PrintMaze(int** maze, int n, int m) {

    printf("\n");

    for (int i = 0; i < n; i++) {

        for (int j = 0; j < m; j++) {

            printf("%d ", maze[i][j]);

        }

        printf("\n");

    }

    printf("\n");

}

bool IsPass(int** maze, int n, int m, PT pos) {

    if (pos.row >= 0 && pos.row < n

            && pos.col >= 0 && pos.col < m

            && maze[pos.row][pos.col] == 1)

        return true;

    else

        return false;

}

//打印路径

void PrintPath(ST* ps) {

    ST rPath;

    StackInit(&rPath);

    //把path栈倒到另一个rpath栈中

    while (!StackEmpty(ps)) {

        StackPush(&rPath, StackTop(ps));

        StackPop(ps);

    }

    while (StackSize(&rPath) > 1) {

        PT top = StackTop(&rPath);

        printf("[%d,%d],", top.row, top.col);

        StackPop(&rPath);

    }

    PT top = StackTop(&rPath);

    printf("[%d,%d]", top.row, top.col);

    StackPop(&rPath);


 

    StackDestory(&rPath);

}

//拷贝栈

void StackCopy(ST* ppath, ST* pcopy) {

    pcopy->a = (STDataType*)malloc(sizeof(STDataType) * ppath->capacity);

    memcpy(pcopy->a, ppath->a, sizeof(STDataType)*ppath->top);

    pcopy->top = ppath->top;

    pcopy->capacity = ppath->capacity;

}

void GetMazePath(int** maze, int n, int m, PT cur, int p) {

    //入栈

    StackPush(&path, cur);

    //走到出口

    if (cur.row == 0 && cur.col == m - 1) {

        //如果找到了更短路径就更新

        if (p>=0 && StackEmpty(&minpath) || StackSize(&path) < StackSize(&minpath)) {

            StackDestory(&minpath);

            StackCopy(&path, &minpath);

        }

    }

    //探测cur位置的上下左右四个方向

    PT next;

    //先把自己改成2表示已走过

    maze[cur.row][cur.col] = 2;

    //上

    next = cur;

    next.row -= 1;

    if (IsPass(maze, n, m, next)) {

        GetMazePath(maze, n, m, next, p - 3);

    }

    //下

    next = cur;

    next.row += 1;

    if (IsPass(maze, n, m, next)) {

        GetMazePath(maze, n, m, next, p );

    }

    //左

    next = cur;

    next.col -= 1;

    if (IsPass(maze, n, m, next)) {

        GetMazePath(maze, n, m, next, p - 1);

    }

    //右

    next = cur;

    next.col += 1;

    if (IsPass(maze, n, m, next)) {

        GetMazePath(maze, n, m, next, p - 1);

    }

    //四个方向都不通,出栈

    //恢复可走路径

    maze[cur.row][cur.col] = 1;

    StackPop(&path);

}

int main() {

    StackInit(&path);

    StackInit(&minpath);

    int n;

    int m;

    int p;

    //printf("请输入迷宫长宽、和体力值:");

    while (scanf("%d %d %d", &n, &m, &p) != EOF) {

        int** maze = (int**)malloc(sizeof(int*) * n);

        for (int i = 0; i < n; i++) {

            maze[i] = (int*)malloc(sizeof(int) * m);

        }

       

        //输入迷宫

        for (int i = 0; i < n; i++) {

            for (int j = 0; j < m; j++) {

                scanf("%d", &maze[i][j]);

            }

        }

        PT entry = { 0, 0 };

        //PrintMaze(maze, n, m);

        GetMazePath(maze, n, m, entry, p);

       

        if (!StackEmpty(&minpath))

           {

                PrintPath(&minpath);

           }

        else

         {

            printf("Can not escape!");

         }

        //PrintMaze(maze, n, m);

        StackDestory(&path);

        StackDestory(&minpath);

        //释放数据

        for (int i = 0; i < n; i++) {

            free(maze[i]);

        }

        free(maze);

        maze = NULL;

    }


 

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值