1. 程式人生 > >【NOJ1009】【演算法實驗二】【DFS_回溯】迷宮問題

【NOJ1009】【演算法實驗二】【DFS_回溯】迷宮問題

1009.迷宮問題

時限:1000ms 記憶體限制:10000K  總時限:3000ms

描述

給一個20×20的迷宮、起點座標和終點座標,問從起點是否能到達終點。

輸入

多個測例。輸入的第一行是一個整數n,表示測例的個數。接下來是n個測例,每個測例佔21行,第一行四個整數x1,y1,x2,y2是起止點的位置(座標從零開始),(x1,y1)是起點,(x2,y2)是終點。下面20行每行20個字元,’.’表示空格;’X’表示牆。

輸出

每個測例的輸出佔一行,輸出Yes或No。

【第二版程式碼】學會了一個用陣列計算新格子橫縱座標的方法,不需要用switch判斷具體方向和複雜的false條件,又重寫了moveto函式,去掉了冗餘的canmoveto函式,使程式碼更加簡潔美觀啦。(第一版刪掉了太丟臉了)

#include <iostream>

using namespace std;

char maze[20][20];  //存放迷宮
                    //X==牆
                    //.==空
                    //1==已經走過

int n;

int sx,sy;  //start
int tx,ty;  //target

int walk[4][2]= //走一格後橫縱座標變化
{
    0, -1,  //左
    +1, 0,  //下
    0, +1,  //右
    -1, 0   //上
};

void dfs(int m);    //從第m個格子出發開始深搜

int moveto(int x, int y, int d);    //從格子[x][y]能否向方向d走一步
                                    //若能,返回next格子序號
                                    //若不能,返回-1

int main()
{
    cin>>n;
    while(n--)
    {
        //輸入資料
        cin>>sx>>sy>>tx>>ty;
        cin.get();          //重點!不要忘記吃第一行末尾的換行符
        for(int i=0; i<20; i++)
        {
            for(int j=0; j<20; j++)
            {
                maze[i][j]=cin.get();
            }
            cin.get();  //吃掉每一行末尾的換行符
        }

        //演算法執行
        dfs(sx*20+sy);

        //輸出資料
        if(maze[tx][ty]=='1')
        {
            cout<<"Yes"<<endl;
        }
        else
        {
            cout<<"No"<<endl;
        }
    }
    return 0;
}

void dfs(int m) //從第m個格子出發搜尋
{
    int x=m/20;
    int y=m%20;

    maze[x][y]='1'; //標記已經到達

    int next;
    for(int d=0; d<4; d++)  //向4個方向試探,0==左,1==下,2==右,3==上
    {
        next=moveto(x, y, d);   //若能向d方向走,就返回走一步後的格子序號next
        if(next>=0)             //若不能向d方向走,moveto函式返回給next的值是-1
        {
            dfs(next);
        }
    }
}

//越界判斷、是牆判斷、重複判斷
int moveto(int x, int y, int d)     //從格子[x][y]能否向方向d走一步
{
    int nextx=x+walk[d][0]; //獲取新座標
    int nexty=y+walk[d][1];

    if(nextx<20&&nextx>=0&&nexty<20&&nexty>=0)  //不越界
    {
        if(maze[nextx][nexty]=='.')     //不是牆且不重複
        {
            return (nextx*20+nexty);  //返回新格子序號
        }
    }
    return -1;  //無法通行,返回-1
}