1. 程式人生 > >【NOJ1042】【分支限界法】電子老鼠走迷宮

【NOJ1042】【分支限界法】電子老鼠走迷宮

1042.電子老鼠闖迷宮

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

描述

有一隻電子老鼠被困在如下圖所示的迷宮中。這是一個12*12單元的正方形迷宮,黑色部分表示建築物,白色部分是路。電子老鼠可以在路上向上、下、左、右行走,每一步走一個格子。現給定一個起點S和一個終點T,求出電子老鼠最少要幾步從起點走到終點。(迷宮左上角為[1, 1])

輸入

本題包含一個測例。在測例的第一行有四個由空格分隔的整數,分別表示起點的座標S(x.y)和終點的座標T(x,y)。

從第二行開始的12行中,每行有12個字元,描述迷宮的情況,其中'X'表示建築物,'.'表示路.

輸出

輸出一個整數,即電子老鼠走出迷宮至少需要的步數。

#include <iostream>
#include <queue>

using namespace std;

struct Node //用一個結構體存放當前在迷宮中的位置/狀態
{
    int x;  //當前狀態橫座標,從1開始
    int y;  //當前狀態縱座標,從1開始
};

queue <Node> state; //結構體佇列
                    //這是自己寫的第一個結構體佇列,值得紀念,液!

char maze[13][13];  //存放迷宮,從[1,1]開始
int used[13][13];   //當前格子是否已訪問過
int step[13][13];   //存放從起點走到當前格子需要走的步數

bool canmoveto(int x,int y,int d);  //判斷方格[x,y]能否向方向d走一步

Node moveto(int x,int y,int d);     //返回方格[x,y]向d走一步之後到達的格子node

int main()
{
    Node start,target;  //起點結構體與終點結構體
    cin>>start.x>>start.y>>target.x>>target.y;
    for(int i=1;i<=12;i++)
    {
        for(int j=1;j<=12;j++)
        {
            cin>>maze[i][j];
        }
    }

    state.push(start);          //起點入隊
    used[start.x][start.y]=1;   //標記起點訪問過
    step[start.x][start.y]=0;   //從起點走到起點需要0步

    Node top,next;
    while(!state.empty())
    {
        top=state.front();  //取隊首元素
        state.pop();

        for(int d=0; d<4; d++)  //向四個方向試探
        {
            if(canmoveto(top.x,top.y,d))    //如果方向d能走
            {
                next=moveto(top.x,top.y,d); //向方向d走一步,走到next格子
                used[next.x][next.y]=1;     //標記next格子被訪問過
                step[next.x][next.y]=step[top.x][top.y]+1;  //走到next格子的步數比走到top格子的步數多一步
                state.push(next);           //將next入隊
                //cout<<next.x<<' '<<next.y<<' '<<step[next.x][next.y]<<endl;
            }
        }
        if(next.x==target.x&&next.y==target.y)  //如果next格子就是目標格子,那麼退出
        {
            break;
        }
    }

    cout<<step[target.x][target.y]<<endl;
    return 0;
}


//不能走的條件:越界、為牆、已訪問過
bool canmoveto(int x,int y,int d)   //判斷方格[x,y]能否向方向d走一步
{
    switch(d)
    {
        case 0: //左
        {
            if(y-1<1||maze[x][y-1]=='X'||used[x][y-1]==1)
            {
                return false;
            }
            else
            {
                break;
            }
        }
        case 1: //下
        {
            if(x+1>12||maze[x+1][y]=='X'||used[x+1][y]==1)
            {
                return false;
            }
            else
            {
                break;
            }
        }
        case 2: //右
        {
            if(y+1>12||maze[x][y+1]=='X'||used[x][y+1]==1)
            {
                return false;
            }
            else
            {
                break;
            }
        }
        case 3: //上
        {
            if(x-1<1||maze[x-1][y]=='X'||used[x-1][y]==1)
            {
                return false;
            }
            else
            {
                break;
            }
        }
    }
    return true;
}

Node moveto(int x,int y,int d)      //返回方格[x,y]向d走一步之後到達的格子node
{
    Node next;
    switch(d)
    {
        case 0: //左
        {
            next.x=x;
            next.y=y-1;
            break;
        }
        case 1: //下
        {
            next.x=x+1;
            next.y=y;
            break;
        }
        case 2: //右
        {
            next.x=x;
            next.y=y+1;
            break;
        }
        case 3: //上
        {
            next.x=x-1;
            next.y=y;
            break;
        }
    }
    return next;
}

【後記】

1.程式碼寫到現在,寫的第一個結構體佇列!作為一個當初自己瞎啃資料結構被難到哭泣的人,開森!