1. 程式人生 > >SDJZUOJ迷宮問題(BFS)

SDJZUOJ迷宮問題(BFS)

題目描述

小明置身於一個迷宮,請你幫小明找出從起點到終點的最短路程。
小明只能向上下左右四個方向移動。

輸入格式

輸入包含多組測試資料。輸入的第一行是一個整數T,表示有T組測試資料。
每組輸入的第一行是兩個整數N和M(1<=N,M<=100)。
接下來N行,每行輸入M個字元,每個字元表示迷宮中的一個小方格。
字元的含義如下:
‘S’:起點
‘E’:終點
‘-’:空地,可以通過
‘#’:障礙,無法通過
輸入資料保證有且僅有一個起點和終點。

輸出

對於每組輸入,輸出從起點到終點的最短路程,如果不存在從起點到終點的路,則輸出-1。

樣例輸入

1
5 5
S-###
-----
##---
E#---
---##

樣例輸出

9

</pre><pre name="code" class="cpp">/*
1
5 5
S-###
-----
##---
E#---
---##
*/
#include<stdio.h>
#include<iostream>
using namespace std;
struct note
{
    int x;//橫座標
    int y;//縱座標
    int s;//走的步數
};
struct note que[2051];
char a[51][51];
int i,j,k,n,m,startx,starty,p,q,ty,tx,flag;

int book[51][51];
int next[4][2]={{0,1},
                {1,0},
                {0,-1},
                {-1,0}};
void bfs()
{
        //佇列初始化
    int head=1;
    int tail=1;
    //往佇列插入迷宮的入口座標
    que[tail].x=startx;
    que[tail].y=starty;
    que[tail].s=0;
    tail++;
    book[startx][starty]=1;
    flag=0;//用來標記是否到達目的地,0表示沒有
    while(head<tail)//當佇列不為空時候
    {
        //列舉四個方向(注意方向陣列的設定和for迴圈的遍歷,通用模板)
        for(k=0;k<=3;k++)
        {
            //計算下一個點座標
            tx=que[head].x+next[k][0];
             ty=que[head].y+next[k][1];
             //判斷是否越界
             if(tx<1||tx>n||ty<1||ty>n)
                 continue;
            //判斷是否是障礙物或者已經在路徑中
            if(a[tx][ty]!='#'&&book[tx][ty]==0)//此處不能寫 a[tx][ty]=='-',因為這樣起點就進不了佇列中
            {
                //把這個點標記為已經走過
                //注意寬頻搜尋每個點只能入佇列一次 ,和dfs不同,所以book的值不需要恢復為0;
                book[tx][ty]=1;
                //插入新的點到佇列中
                que[tail].x =tx;
                que[tail].y=ty;
                que[tail].s=que[head].s+1;
                tail++;
             }
             //如果到了目的地,停止擴充套件,任務結束,退出迴圈
             if(tx==p&&ty==q)
             {
                 //注意這兩句話千萬位置不能顛倒
                 flag=1;
                 break;
    
              }
              
         }
         if(flag==1)
             break;
         head++;//這個地方千萬不能忘記,當一個點擴充套件結束後,head++才能使得後面的點再進行擴充套件
     }
     //列印佇列中末尾最後一個點的步數
     //注意tail是指向隊尾的下一個位置,所以需要-1
     cout<<que[tail-1].s;          
}
int main()
{
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            cin>>a[i][j];
            if(a[i][j]=='S')
            {
                startx=i;
                starty=j;
            }
            if(a[i][j]=='E')
            {
                p=i;
                q=j;
            }                
        }
    }
    bfs();
    return 0;

 }