1. 程式人生 > >迷宮問題的通用解法C語言資料結構實現

迷宮問題的通用解法C語言資料結構實現

1.1問題描述
以一個m*n的長方陣表示迷宮,0和1分別表示迷宮中的通路和障礙。設計一個程式,對任意設定的迷宮,求出一條從入口到出口的通路,或得出沒有通路的結論。

1.2基本要求
輸入的形式和範圍:
非遞迴:行列為整型,座標為整型

遞迴:迷宮以整型二維陣列形式輸入

輸出的形式:非遞迴輸出三元組通路和方陣通路;
遞迴以方陣輸出迷宮和所有通路;

1、非遞迴演算法,求一條通路輸出三元組形式如:(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2),…和方陣通路;

2、遞迴演算法,求得迷宮中所有可能的通路,以方陣形式輸出迷宮及其通路。

大家先看一個特例:(特例結束後給處通用程式碼:程式碼轉自AHU15電腦科學與技術專業趙吳攀先生,在此鳴謝)

#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;


typedef struct{
    int ord;
    int flag;
    int i;
    int j;
}SElemType;
void di(int &t,int &i,int &j)
{
    if(t==1)
    {
        j=j+1;
    }
    if(t==2)
    {
        i=i+1;
    }
    if
(t==3) { j=j-1; } if(t==4) { i=i-1; } } void ri(int &t,int &m,int &n,int i,int j) { if(t==1) { n=j+1; } if(t==2) { m=i+1; } if(t==3) { n=j-1; } if(t==4) { m=i-1; } } int main() { int
maze[10][10]= { {1,1,2,3,4,5,6,7,8,9}, {1,0,0,1,0,0,0,1,0,1}, {2,0,0,1,0,0,0,1,0,1}, {3,0,0,0,0,1,1,0,0,1}, {4,0,1,1,1,0,0,0,0,1}, {5,0,0,0,1,0,0,0,0,1}, {6,0,1,0,0,0,1,0,0,1}, {7,0,1,1,1,0,1,1,0,1}, {8,1,0,0,0,0,0,0,0,1}, {9,1,1,1,1,1,1,1,1,1} }; int curstep=1,m=1,n=1; int tag=0; SElemType e; e.flag=1;e.i=1,e.j=1; stack<SElemType>S; do { if(maze[m][n]<=0) { maze[m][n]=1; e.ord=curstep; e.i=m;e.j=n; e.flag=1; S.push(e); if(m==8&&n==8){tag=1;break;} else{ di(e.flag,m,n); printf("%d %d\n",m,n); curstep++; } } else{ if(!S.empty()){ e=S.top(); S.pop(); while(e.flag==4&&!S.empty()){ maze[m][n]=1; e=S.top(); S.pop(); } if(e.flag<4){ e.flag++; S.push(e); ri(e.flag,m,n,e.i,e.j); } } } }while(!S.empty()); if(tag==1) printf("SUCCESS!"); else printf("ERROR!"); }

遞迴程式碼:

#include <stdio.h>
#include <malloc.h>
#define M 6
#define N 6
#define END N-2
int flag=0;
typedef struct
{
    int x,y,d;
}position;

/*建立迷宮*/
void creat_maze(int a[][M])
{
    int i,j;
    for(i=0;i<=N-1;i++)
        for(j=0;j<=M-1;j++)
        scanf("%1d",&a[i][j]);
}

position nextq(int maze[][M],position q)
{
    if(q.d==0)
        q.y++;
    else if(q.d==1)
        q.x++;
    else if(q.d==2)
        q.y--;
    else if(q.d==3)
        q.x--;
    return q;
}
void initialmat(int route[][M])       //初始化輸出路徑圖
{
    int i,j;
    for(i=0;i<N;i++)
        for(j=0;j<M;j++)
            route[i][j]=1;
}
void print_maze(int mat[][M])        //輸出迷宮
{
    int i,j;
    for(i=0;i<N;i++)
        {
        for(j=0;j<M;j++)
           printf("%d ",mat[i][j]);
           printf("\n");
        }

}
void MazePath(int maze[][M],int route[][M],position ps)
{
    position q;
    route[ps.x][ps.y]=0;
    maze[ps.x][ps.y]=-1;
    q=nextq(maze,ps);
    q.d=0;
    if(q.x==END&&q.y==END)
    {
        flag++;
        printf("\n第%d條路:\n",flag);
        route[END][END]=0;
        print_maze(route);
        route[END][END]=1;
    }
    else if(maze[q.x][q.y]==0)
        MazePath(maze,route,q);
    if(ps.d<=3)
    {
        ps.d++;
        MazePath(maze,route,ps);
    }
    route[ps.x][ps.y]=1;
    maze[ps.x][ps.y]=0;
}
void main()
{
    int maze[N][M],route[N][M];
    position ps;
    ps.x=ps.y=1;
    ps.d=0;
    printf("輸入一個迷宮(%d*%d):\n",N,M);
    creat_maze(maze);
    printf("\n輸出該迷宮:\n");
    print_maze(maze);
    printf("輸出從(1,1)到(%d,%d)的所有通路:\n",N-2,M-2);
    initialmat(route);
    MazePath(maze,route,ps);
}

非遞迴程式碼:

#include<stdio.h>
#include<stdlib.h>
#define Elemtype int
#define MAXSIZE 50
typedef struct
{
    int x,y;
}mark;               //起點、終點座標

typedef struct
{
    Elemtype x,y;    //迷宮陣列座標(x,y)
    int d;    //下一步的方向
}TriMatrix;

typedef struct LStackNode
{
    TriMatrix elem;
    struct LStackNode *next;
}LStack,*PLStack;

//棧的基本操作

PLStack InitStack(PLStack S)
{
    S=NULL;
    return S;
}

int StackEmpty(PLStack S)
{
    if(S==NULL)  return 1;
    else return 0;
}

PLStack Push(PLStack S,TriMatrix e)   //入棧
{
    PLStack P;
    P=(PLStack)malloc(sizeof(LStack));
    P->elem=e;
    P->next=S;
    S=P;
    return S;
}

PLStack Delete(PLStack S)   //刪除棧頭
{
    PLStack P;
    P=S;
    if(!StackEmpty(S))
    {
        S=S->next;
        free(P);
        return S;
    }
}

TriMatrix Pop(PLStack S,TriMatrix e)  //出棧
{
    if(!StackEmpty(S))
    {
        e=S->elem;
        return e;
    }
}

void MazePath(mark start,mark end,
              Elemtype maze[MAXSIZE][MAXSIZE],
              int m,int n,int diradd[4][2])   //尋找路徑
{
    int i,j,d;
    int a,b;
    TriMatrix elem,e;
    PLStack S1,S2;
    S1=InitStack(S1);
    S2=InitStack(S2);
    maze[start.x][start.y]=2;   //修改入口座標,做標記
    elem.x=start.x;
    elem.y=start.y;
    elem.d=0;  //開始為0
    S1=Push(S1,elem);
    while(!StackEmpty(S1))  //棧不空,有路可走
    {
        elem=Pop(S1,elem);
        S1=Delete(S1);
        i=elem.x;
        j=elem.y;
        d=elem.d+1;
        while(d<=4)
        {
            a=i+diradd[d-1][0];
            b=j+diradd[d-1][1];
            if(a==end.x&&b==end.y&&maze[a][b]==0)  //出口
            {
                elem.x=i;
                elem.y=j;
                elem.d=d;
                S1=Push(S1,elem);
                elem.x=a;
                elem.y=b;
                elem.d=0;   //方向輸出為0,判斷是否為出口
                S1=Push(S1,elem);
                printf("\n1=東 2=南 3=西 4=北 0為走出迷宮\n\n路徑為:(行座標,列座標,方向)\n");
                while(S1)  //逆置序列 並輸出路徑
                {
                    e=Pop(S1,e);
                    S1=Delete(S1);
                    S2=Push(S2,e);
                }
                while(S2)
                {
                    e=Pop(S2,e);
                    S2=Delete(S2);
                    printf("-->(%d,%d,%d)",e.x,e.y,e.d);maze[e.x][e.y]=3;
                }
                printf("\n\n");
                for(i=0;i<=m+1;i++){
                for(j=0;j<=n+1;j++)
                    if(maze[i][j]==3) printf("0 ");
                    else printf("1 ");
                    printf("\n");
                }
                return;
            }//if
            if(maze[a][b]==0)
            {
                maze[a][b]=2;
                elem.x=i;
                elem.y=j;
                elem.d=d;
                S1=Push(S1,elem);
                i=a;  j=b;  d=0;
            }
            d++;
        }
    }
    printf("沒有出迷宮的路徑\n");
}

//建立迷宮
void initmaze(int maze[MAXSIZE][MAXSIZE],int m,int n)
{
    int i,j;
    for(i=1;i<=m;i++)
        for(j=1;j<=n;j++)
        maze[i][j]=rand()%2;
    for(i=0;i<=m+1;i++)
    {
        maze[i][0]=maze[i][n+1]=1;
    }
    for(j=0;j<=n+1;j++)
    {
        maze[0][j]=maze[m+1][j]=1;
    }
    printf("輸出迷宮:\n");
    for(i=0;i<=m+1;i++)
    {
        for(j=0;j<=n+1;j++)
        printf("%d ",maze[i][j]);
        printf("\n");
    }
}

void main()
{
    int maze[MAXSIZE][MAXSIZE];
    mark start,end;
    int m,n;  //迷宮行列
    printf("輸入迷宮的行數m和列數n:\n");
    scanf("%d%d",&m,&n);
    int add[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
    initmaze(maze,m,n);
    printf("輸入入口座標和出口座標:\n");
    scanf("%d%d%d%d",&start.x,&start.y,&end.x,&end.y);
    MazePath(start,end,maze,m,n,add);
}

相關推薦

迷宮問題的通用解法C語言資料結構實現

1.1問題描述 以一個m*n的長方陣表示迷宮,0和1分別表示迷宮中的通路和障礙。設計一個程式,對任意設定的迷宮,求出一條從入口到出口的通路,或得出沒有通路的結論。 1.2基本要求 輸入的形式和範圍: 非遞迴:行列為整型,座標為整型 遞迴:迷宮以整型二維

c語言資料結構實現-雜湊表/雜湊桶(hashtable/hashbucket)

一、需求 以“key-value”的形式進行插入、查詢、刪除,是否可以考慮犧牲空間換時間的做法? 二、相關知識 雜湊表(Hashtable)又稱為“雜湊表”,Hashtable是會根據索引鍵的雜湊程式程式碼組織成的索引鍵(Key)和值(Value)配對的集合。Hashtab

C語言資料結構用 棧 實現進位制轉化

直接上程式碼,思路看註釋; /*棧實現進位制轉化 *十進位制最大轉化為36進位制用10(A)-35(Z)表示 */ #include<stdio.h> #include<malloc.h> #include<stdlib.h> #

C語言資料結構之靜態連結串列實現(A-B)U(B-A)

時間複雜度O(3n)不是很難,直接貼程式碼:StaticLinkList.h#ifndef _STATIC_LINK_LIST_H_ #define _STATIC_LINK_LIST_H_ #define MAXSIZE 100 typedef enum {ERROR,OK

C語言資料結構----棧的定義及實現

本節主要說的是資料結構中的棧的基本定義和實現的方式,其中實現的方式採用的是複用順序表和單向連結串列的方式。 一、棧的基本定義 1.棧是一種特殊的線性表,只能從固定的方向進出,而且棧進出的基本原則是:先進棧的元素後出棧。 2.老唐對棧頂棧底的定義: 棧頂:允許操作的一端。

C語言資料結構-順序佇列-陣列實現

#include <stdio.h> #include <stdlib.h> typedef struct SQueue{ int * data; int front,rear; int maxSize; } SQueue;

C語言資料結構演算法實現圖的遍歷

   假設給定圖G的初態是所有頂點均未曾訪問過。在G中任選一頂點v為初始出發點(源點),則深度優先遍歷可定義如下:首先訪問出發點v,並將其標記為已訪問過;然後依次從v出發搜尋v的每個鄰接點w。若w未曾訪問過,則以w為新的出發點繼續進行深度優先遍歷,直至圖中所有和源點v有路徑相通(從源點可達)的頂點均已被訪問為

C語言資料結構-棧-陣列實現

#include <stdio.h> #include <stdlib.h> #define DEFAULT_SIZE 50 typedef struct ArrayStack{ int *dataArray; int top;

C語言資料結構——雙迴圈連結串列的插入操作順序

雙向連結串列與單鏈表的插入操作的區別 雙向連結串列因為存在前驅指標和後繼指標所以需要修改的指標多於單鏈表,但指標改動的順序同樣重要 單鏈表的插入 eg:在節點p的後面插入指標s s->next=p->next;//首先要使要插入的指標指向p->next p->next=s

C語言資料結構-二叉樹、哈夫曼、佇列小練習

原始碼地址 GitHub:https://github.com/GYT0313/C-DataStructure 1. 二叉樹 要求: 掌握二叉樹的二叉連結串列的建立方法; 掌握二叉樹的3種遍歷遞迴演算法; 掌握二叉樹的3種遍歷的非遞迴演算法。 程式

C語言資料結構與演算法之深度、廣度優先搜尋

一、深度優先搜尋(Depth-First-Search 簡稱:DFS) 1.1 遍歷過程:   (1)從圖中某個頂點v出發,訪問v。   (2)找出剛才第一個被頂點訪問的鄰接點。訪問該頂點。以這個頂點為新的頂點,重複此步驟,直到訪問過的頂點沒有未被訪問過的頂點為止。   (3)返回到

C語言資料結構——一步步教會你尾插法和頭插法

連結串列也是線性表的一種,與順序表不同的是,它在記憶體中不是連續存放的。在C語言中,連結串列是通過指標相關實現的。而單鏈表是連結串列的其中一種,關於單鏈表就是其節點中有資料域和只有一個指向下個節點的指標域。  建立單鏈表的方法有兩種,分別是頭插法和尾插法。 所謂頭插法,就是按節點的

c語言資料結構之順序表

c語言資料結構之順序表:     順序表的結構跟陣列比起來還是很像的,相比於連結串列,資料表的優勢主要體現在他的查詢速度上,而連結串列的優勢相反,查詢速度慢,但對於插入一個數據來說還是比較快的 下面我們就來建立一個順序表 1:定義資料型別,我定義的是一個學生的結構體型別,首

C語言-資料結構-鏈佇列

** 鏈式佇列 ** 使用兩種不同的方式作為初始化, 特點: 一種是傳遞 Init(&Q); 一種是直接P Q = create(); 我覺得還是這種的方式比較靈活,對比見程式 注:我的習慣是直接寫成標頭檔案,方便呼叫 這個程式使用的 是InitQue

線性表的建立————C語言資料結構學習

#include <stdio.h> #include <malloc.h> #define MaxSize 50 typedef int ElemType; typedef struct { ElemType data[MaxSize];

C語言資料結構——連結串列

轉自https://www.cnblogs.com/chenxiaohei/p/6862791.html /* 連結串列節點的插入與刪除 編譯環境:VC++ 6.0 編譯系統:windows XP SP3 */ #inc

C語言資料結構的簡單實驗——二叉樹的遍歷

實驗題目: 建立一株用二叉連結串列儲存的二叉樹,並對其進行遍歷。 實驗思路: 解題關鍵是要建立二叉樹,因此對語二叉樹的每一個節點,我以連結串列為儲存方式並用遞迴的思想對其進行定義。 ** 程式碼實現: ** #include<stdio.h> #in

C語言資料結構單鏈表之溫故而知新

拋棄繁雜的定義,以實用,實戰的角度來學習資料結構,這將使得資料結構的學習非常的簡單。前面已經學習了單鏈表的建立操作:http://blog.csdn.net/morixinguan/article/details/68951912這節,將單鏈表溫習的筆記共享出來,然後寫一個例

C語言資料結構——求二叉樹葉子結點個數

小編儲存了不少程式碼,最近新開通了CSDN部落格,以前一直看到別人的程式碼分享,深受啟發,非常感謝,所以小編現在也要將自己的程式碼分享給大家,希望大家可以與瀟小白一起在程式設計的道路上越走越遠,早日成為大佬!雖然我目前只是一名大二的學生,不過我會努力噠!加油!

C語言資料結構——分析二叉樹的相似性

程式碼比較簡單,瀟小白就直接放程式碼啦!如果有什麼問題歡迎在下方評論哦!讓我們一起進步,向大佬進發! 程式碼如下: #include <stdio.h> #include <malloc.h> #include <conio