第11周項目5- 迷宮問題之圖深度優先遍歷解法

問題及代碼:

/*
* Copyright(c) 2017,煙臺大學計算機學院
* All rights reserved.
* 文件名稱:cpp1.
* 作    者:薛瑞琪
* 完成日期:2017 年 11 月 14 日
* 版 本 號:v1.0
*
* 問題描述: 設計一個程序,採用深度優先遍歷算法的思路,解決迷宮問題。 
  (1)建立迷宮對應的圖數據結構,並建立其鄰接表表示。 
  (2)採用深度優先遍歷的思路設計算法,輸出從入口(1,1)點到出口(M,N)的所有迷宮路徑。 
* 輸入描述:無需輸入
* 程序輸出:實現各種算法的函數的測試結果
*/

#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
#define M 8
#define N 8
//以下定義鄰接表類型
typedef struct ANode            //邊的結點結構類型
{
    int i,j;                    //該邊的終點位置(i,j)
    struct ANode *nextarc;      //指向下一條邊的指針
} ArcNode;

typedef struct Vnode            //鄰接表頭結點的類型
{
    ArcNode *firstarc;          //指向第一條邊
} VNode;

typedef struct
{
    VNode adjlist[M+2][N+2];    //鄰接表頭節點數組
} ALGraph;                      //圖的鄰接表類型

typedef struct
{
    int i;                      //當前方塊的行號
    int j;                      //當前方塊的列號
} Box;

typedef struct
{
    Box data[MaxSize];
    int length;                 //路徑長度
} PathType;                     //定義路徑類型

int visited[M+2][N+2]= {0};
int count=0;
void CreateList(ALGraph *&G,int mg[][N+2])
//建立迷宮數組對應的鄰接表G
{
    int i,j,i1,j1,di;
    ArcNode *p;
    G=(ALGraph *)malloc(sizeof(ALGraph));
    for (i=0; i<M+2; i++)                   //給鄰接表中所有頭節點的指針域置初值
        for (j=0; j<N+2; j++)
            G->adjlist[i][j].firstarc=NULL;
    for (i=1; i<=M; i++)                    //檢查mg中每個元素
        for (j=1; j<=N; j++)
            if (mg[i][j]==0)
            {
                di=0;
                while (di<4)
                {
                    switch(di)
                    {
                    case 0:
                        i1=i-1;
                        j1=j;
                        break;
                    case 1:
                        i1=i;
                        j1=j+1;
                        break;
                    case 2:
                        i1=i+1;
                        j1=j;
                        break;
                    case 3:
                        i1=i, j1=j-1;
                        break;
                    }
                    if (mg[i1][j1]==0)                          //(i1,j1)爲可走方塊
                    {
                        p=(ArcNode *)malloc(sizeof(ArcNode));   //創建一個節點*p
                        p->i=i1;
                        p->j=j1;
                        p->nextarc=G->adjlist[i][j].firstarc;   //將*p節點鏈到鏈表後
                        G->adjlist[i][j].firstarc=p;
                    }
                    di++;
                }
            }
}
//輸出鄰接表G
void DispAdj(ALGraph *G)
{
    int i,j;
    ArcNode *p;
    for (i=0; i<M+2; i++)
        for (j=0; j<N+2; j++)
        {
            printf("  [%d,%d]: ",i,j);
            p=G->adjlist[i][j].firstarc;
            while (p!=NULL)
            {
                printf("(%d,%d)  ",p->i,p->j);
                p=p->nextarc;
            }
            printf("\n");
        }
}
void FindPath(ALGraph *G,int xi,int yi,int xe,int ye,PathType path)
{
    ArcNode *p;
    visited[xi][yi]=1;                   //置已訪問標記
    path.data[path.length].i=xi;
    path.data[path.length].j=yi;
    path.length++;
    if (xi==xe && yi==ye)
    {
        printf("  迷宮路徑%d: ",++count);
        for (int k=0; k<path.length; k++)
            printf("(%d,%d) ",path.data[k].i,path.data[k].j);
        printf("\n");
    }
    p=G->adjlist[xi][yi].firstarc;  //p指向頂點v的第一條邊頂點
    while (p!=NULL)
    {
        if (visited[p->i][p->j]==0) //若(p->i,p->j)方塊未訪問,遞歸訪問它
            FindPath(G,p->i,p->j,xe,ye,path);
        p=p->nextarc;               //p指向頂點v的下一條邊頂點
    }
    visited[xi][yi]=0;
}

int main()
{
    ALGraph *G;
    int mg[M+2][N+2]=                           //迷宮數組
    {
        {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,0,1,1,1,0,1},
        {1,1,0,0,0,0,0,0,0,1},
        {1,1,1,1,1,1,1,1,1,1}
    };
    CreateList(G,mg);
    printf("迷宮對應的鄰接表:\n");
    DispAdj(G); //輸出鄰接表
    PathType path;
    path.length=0;
    printf("所有的迷宮路徑:\n");
    FindPath(G,1,1,M,N,path);
    return 0;
}

運行結果:


學習心得:

在看了例題了解了解題思想後,我用如下迷宮進行了測試。


知識點總結:

①此類題型應當首先建立模型。

將迷宮中的每一格作爲一個頂點,相鄰格子可以到達,則對應的頂點之間存在邊相連。 例如:


②在使用數組表示時,用0表示格子是空地,用1表示格子處是牆,寫出對應的矩陣。


③建立圖結構


④將從(1,1)到(4,4)的迷宮問題,轉化爲尋找頂點(1,1)到頂點(4,4)的路徑的問題。




發佈了80 篇原創文章 · 獲贊 6 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章