C语言求解迷宫问题
迷宮問(wèn)題求解
https://www.nowcoder.com/questionTerminal/cf24906056f4488c9ddb132f317e03bc
以上迷宮OJ題曾經(jīng)是百度某一年的其中一個(gè)筆試題,
迷宮問(wèn)題本質(zhì)就是一個(gè)圖的遍歷問(wèn)題,從起點(diǎn)開(kāi)始不斷四個(gè)方向探索,直到走到出口,
走的過(guò)程中我們借助棧記錄走過(guò)路徑的坐標(biāo),棧記錄坐標(biāo)有兩方面的作用,
一方面是記錄走過(guò)的路徑,一方面方便走到死路時(shí)進(jìn)行回溯找其他的通路。
輸入兩個(gè)整數(shù),分別表示二維數(shù)組的行數(shù),列數(shù)。
再輸入相應(yīng)的數(shù)組,其中的1表示墻壁,0表示可以走的路。
數(shù)據(jù)保證有唯一解,不考慮有多解的情況,即迷宮只有一條通道。
5 5
0 1 0 0 0
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
題解
關(guān)于求解,肯定是先創(chuàng)建一個(gè)自身位置的結(jié)構(gòu)體,由于c語(yǔ)言沒(méi)有那么多庫(kù)函數(shù),所以我們只能自己寫(xiě)一個(gè)棧了
#include<stdio.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h> typedef struct Postion {int row;int col; }PT; typedef PT STDataType; // 支持動(dòng)態(tài)增長(zhǎng)的棧 typedef struct Stack {STDataType* a;int top; // 棧頂int capacity; // 容量 }Stack, ST; // 初始化棧 void StackInit(Stack* ps); // 入棧 void StackPush(Stack* ps, STDataType data); // 出棧 void StackPop(Stack* ps); // 獲取棧頂元素 STDataType StackTop(Stack* ps); // 獲取棧中有效元素個(gè)數(shù) int StackSize(Stack* ps); // 檢測(cè)棧是否為空,如果為空返回非零結(jié)果,如果不為空返回0 bool StackEmpty(Stack* ps); // 銷(xiāo)毀棧 void StackDestroy(Stack* ps); // 初始化棧 void StackInit(Stack* ps) {assert(ps);ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);if (ps->a == NULL){printf("malloc fail\n");exit(-1);}ps->capacity = 4;ps->top = 0; } // 入棧 void StackPush(Stack* ps, STDataType data) {assert(ps);//滿(mǎn)了 -> 擴(kuò)容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] = data;ps->top++; } // 出棧 void StackPop(Stack* ps) {assert(ps);assert(ps->top > 0);ps->top--; } // 獲取棧頂元素 STDataType StackTop(Stack* ps) {assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1]; } // 獲取棧中有效元素個(gè)數(shù) int StackSize(Stack* ps) {assert(ps);return ps->top; } // 檢測(cè)棧是否為空,如果為空返回非零結(jié)果,如果不為空返回0 bool StackEmpty(Stack* ps) {assert(ps);return ps->top == 0; } // 銷(xiāo)毀棧 void StackDestroy(Stack* ps) {assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0; } ///棧寫(xiě)好之后,就開(kāi)始進(jìn)入求解路徑了,首先得創(chuàng)建一個(gè)迷宮,獲取迷宮地圖,初始化自身位置,開(kāi)始上下左右判斷移動(dòng),為0表示無(wú)障礙,可以走;
這里就可以用遞歸來(lái)完成,走過(guò)的路要改成除0和1外的數(shù)(這里我用2來(lái)代替了),不然又會(huì)走重;當(dāng)走到死路時(shí),就需要往回走,回到一個(gè)有第二個(gè)方向可以走的位置,被稱(chēng)為回溯,還用到了棧的先進(jìn)后出,所以用棧來(lái)記錄路徑是最好不夠了;
//主函數(shù)
int main() {int N = 0, M = 0;while (scanf("%d%d", &N, &M) != EOF){//創(chuàng)建迷宮,獲取迷宮地圖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);PT entry = { 0,0 };if (GetMazePath(maze, N, M, entry)){PrintPath(&Path);}else{printf("沒(méi)有找到通路\n");}//銷(xiāo)毀迷宮StackDestroy(&Path);for (int i = 0; i < N; ++i){free(maze[i]);}free(maze);maze = NULL;}return 0; }迷宮最短路徑求解
小青蛙有一天不小心落入了一個(gè)地下迷宮,小青蛙希望用自己僅剩的體力值P跳出這個(gè)地下迷宮。
為了讓問(wèn)題簡(jiǎn)單,假設(shè)這是一個(gè)n*m的格子迷宮,迷宮每個(gè)位置為0或者1,
0代表這個(gè)位置有障礙物,小青蛙達(dá)到不了這個(gè)位置;1代表小青蛙可以達(dá)到的位置。
小青蛙初始在(0,0)位置,地下迷宮的出口在(0,m-1)
(保證這兩個(gè)位置都是1,并且保證一定有起點(diǎn)到終點(diǎn)可達(dá)的路徑),
小青蛙在迷宮中水平移動(dòng)一個(gè)單位距離需要消耗1點(diǎn)體力值,
向上爬一個(gè)單位距離需要消耗3個(gè)單位的體力值,向下移動(dòng)不消耗體力值,
當(dāng)小青蛙的體力值等于0的時(shí)候還沒(méi)有到達(dá)出口,小青蛙將無(wú)法逃離迷宮。
現(xiàn)在需要你幫助小青蛙計(jì)算出能否用僅剩的體力值跳出迷宮(即達(dá)到(0,m-1)位置)。
本題在曾經(jīng)是美團(tuán)某一年的筆試題,
本題在上一個(gè)題的基礎(chǔ)上計(jì)入了體力值的概念,
但是本題還有一個(gè)隱藏條件,就是要找出迷宮的最短路徑,
如下的兩個(gè)測(cè)試用例,需要找出最短路徑,才能通過(guò)全部測(cè)試用例
4 4 10 1 0 0 1 1 1 0 1 0 1 1 1 0 0 1 1
10 10 50 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 0 0 1 0 00 0 0 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 0 0 0 0 0 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 0 0 0 0 0 1 1 0 0 1 1 1 11 1 1
鏈接:https://www.nowcoder.com/questionTerminal/571cfbe764824f03b5c0bfd2eb0a8ddf?f=discussion
題解
同樣的,c語(yǔ)言要自己寫(xiě)一個(gè)棧,和上面是一樣的
#include<stdio.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h> #include<string.h> typedef struct Postion {int row;int col; }PT; typedef PT STDataType; // 支持動(dòng)態(tài)增長(zhǎng)的棧typedef struct Stack {STDataType* a;int top; // 棧頂int capacity; // 容量 }Stack, ST; // 初始化棧 void StackInit(Stack* ps); // 入棧 void StackPush(Stack* ps, STDataType data); // 出棧 void StackPop(Stack* ps); // 獲取棧頂元素 STDataType StackTop(Stack* ps); // 獲取棧中有效元素個(gè)數(shù) int StackSize(Stack* ps); // 檢測(cè)棧是否為空,如果為空返回非零結(jié)果,如果不為空返回0 bool StackEmpty(Stack* ps); // 銷(xiāo)毀棧 void StackDestroy(Stack* ps); // 初始化棧 void StackInit(Stack* ps) {assert(ps);ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);if (ps->a == NULL){printf("malloc fail\n");exit(-1);}ps->capacity = 4;ps->top = 0; } // 入棧 void StackPush(Stack* ps, STDataType data) {assert(ps);//滿(mǎn)了 -> 擴(kuò)容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] = data;ps->top++; } // 出棧 void StackPop(Stack* ps) {assert(ps);assert(ps->top > 0);ps->top--; } // 獲取棧頂元素 STDataType StackTop(Stack* ps) {assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1]; } // 獲取棧中有效元素個(gè)數(shù) int StackSize(Stack* ps) {assert(ps);return ps->top; } // 檢測(cè)棧是否為空,如果為空返回非零結(jié)果,如果不為空返回0 bool StackEmpty(Stack* ps) {assert(ps);return ps->top == 0; } // 銷(xiāo)毀棧 void StackDestroy(Stack* ps) {assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0; } ///
由于加入了體力值這一變量,路徑也就變?yōu)椴恢挂粭l,所以我們還需要初始化一個(gè)裝最短路徑的棧,由圖,紫色路徑不能滿(mǎn)足體力要求,故需要尋找最優(yōu)路徑;
多條路徑之間不能互相干涉,第一條路徑走完后,迷宮就被修改了,為了不影響第二條路徑,我們需要將迷宮恢復(fù)成沒(méi)走一樣的狀態(tài)
如果不恢復(fù)的話(huà),第二條路徑無(wú)路可走
深淺拷貝問(wèn)題
//找到了更短的路徑,更新minPathif(p >= 0 && StackEmpty(&minPath)|| StackSize(&Path) < StackSize(&minPath)){//找到更短路徑,更新minPath//minPath=Path;StackDestroy(&minPath);StackCopy(&Path,&minPath);}在c語(yǔ)言中,這里=是直接賦值,就是把它的地址存放數(shù)據(jù)的地址給你了,如果寫(xiě)minPath=Pah的話(huà),編譯器提供的就是淺拷貝,再后面釋放內(nèi)存時(shí),Path已經(jīng)將那塊空間釋放了,minPath指向的那塊空間已經(jīng)不是原來(lái)的空間了
總結(jié)
- 上一篇: 从零开始AlignedReID_05
- 下一篇: 【服务器数据集】中心服务器上存放(下载)