0
点赞
收藏
分享

微信扫一扫

数据结构与算法迷宫的最小路径问题分析

数据结构与算法迷宫的最小路径问题分析_i++

这个稍微比迷宫1问题要难了一点,但是大致都是差不多的,只是需要小小的改动一下

这里主要介绍它的注意点:

有多条路但是要找到它的最小路径,还是一样的采用深度优先遍历,递归来实现

1、如果是通道,那是不是走过了就要标记,但是我们找的是最小路径是不是就需要回溯,回溯时就要把标记改为通道1,以防下次就走不通了

2、区分深度拷贝和浅拷贝,代码里也有介绍,minpath = path 浅拷贝,指向了同一块内存空间,当path的内容改变minpath也会改变 ;深度拷贝,path 和 minpath 各占不一样的存储空间,不会互相影响 最好结合代码看

上代码:

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<stdlib.h>

#include<assert.h>

#include <stdbool.h>

#include <string.h>

typedef struct path

{

int row;

int col;

}PAT;

/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

typedef PAT STDataType;

typedef struct Stack

{

STDataType* a;

int top;//指向栈顶就是size

int capacity;//容量

}ST;

void StackInit(ST* ps);//初始化

void StackPrint(const ST* ps);//打印

void StackPush(ST* ps, STDataType x);//入栈

void StackDestroy(ST* ps);//销毁

void StackPop(ST* ps);//出栈

STDataType StackTop(const ST* ps);//取栈顶

int StackSize(const ST* ps);//计算栈的元素

//bool StackEmpty(const ST* ps,int* size);

bool StackEmpty(const ST* ps);//判断栈是否为空

void StackInit(ST* ps)

{

assert(ps);

ps->a = NULL;

ps->capacity = 0;

ps->top = 0;//也可以给 -1

}

//void StackPrint(const ST* ps)

//{

// assert(ps);

// int i;

// for (i = ps->top - 1; i >= 0; i--)

// {

//  printf("%d ", ps->a[i]);

// }

// printf("\n");

//}

void NewStack(ST* ps)

{

int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;

ST* newStack = realloc(ps->a, sizeof(ST) * newcapacity);

if (newStack == NULL)

{

 printf("开辟内存失败");

 exit(-1);

}

ps->a = newStack;

ps->capacity = newcapacity;

}

void StackPush(ST* ps, STDataType x)

{

assert(ps);

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

{

 NewStack(ps);

}

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

ps->top++;

}


void StackPop(ST* ps)

{

assert(ps);

assert(ps->top > 0);

if (ps->top > 0)

 ps->top--;

}

STDataType StackTop(const ST* ps)

{

assert(ps);

assert(ps->top > 0);

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

}

int StackSize(const ST* ps)

{

assert(ps);

return ps->top;

}

bool StackEmpty(ST* ps)

{

return ps->top == 0;

}

void StackDestroy(ST* ps)

{

assert(ps);

free(ps->a); ps->a = NULL;

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

}

ST path;//设置全局栈

ST minpath;


void StackCopy(ST* path, ST* pcopy)

{

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

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

pcopy->top = path->top;

pcopy->capacity = path->capacity;

}

/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

//输出路径坐标

void PrintPath(ST* path)

{

ST rPath;

StackInit(&rPath);

while (!StackEmpty(path))

{

 StackPush(&rPath, StackTop(path));

 StackPop(path);

}

while (StackSize(&rPath)>1)

{

 PAT top = StackTop(&rPath);

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

 StackPop(&rPath);

}

PAT top = StackTop(&rPath);

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

StackPop(&rPath);

StackDestroy(&rPath);

}

void Print(int** maze, int n, int m)

{

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, PAT cur)

{

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

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

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

{

 return true;

}

else

 return false;

}

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

{

StackPush(&path, cur);//先入栈

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

{

 //当 minpath 为空 就把 path 的路径深度拷贝到 minpath 中

 //当 path 找到了一条比 minpath 更短的路径时 就把 path 的路径深度拷贝到 minpath 中

 if (p>=0 && StackEmpty(&minpath)  

  || StackSize(&path) < StackSize(&minpath))

 {

  StackDestroy(&minpath);//把原来的 minpath 释放以免照成内存泄露

  //minpath = path 浅拷贝,指向了同一块内存空间,当path的内容改变minpath也会改变

  //深度拷贝,path 和 minpath 各占不一样的存储空间,不会互相影响

  StackCopy(&path, &minpath);

 }

}

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


//上

PAT next;

next = cur;

next.row -= 1;

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

{

 GetMazePath(maze, n, m, next, p - 3);// 向上移动一个单位消耗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()

{

int n = 0, m = 0,p=0;// p为体力值  水平移动一个单位消耗一个体力值  向上移动一个单位消耗3个体力值 向下不消耗体力值

scanf("%d,%d,%d", &n, &m,&p);

//创建二维数组的行

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]);//输入二维数组的值

 }

}

StackInit(&path);//初始化栈

StackInit(&minpath);//初始化栈

PAT InPath = { 0.0 };

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

if (!StackEmpty(&minpath))

{

 Print(maze, n, m);

 PrintPath(&minpath);

}

else

{

 printf("\n逃离失败!");

}

StackDestroy(&path);

StackDestroy(&minpath);

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

{

 free(maze[i]);

}

free(maze);

maze = NULL;

}


举报

相关推荐

0 条评论