【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入队
                if(next.x==target.x&&next.y==target.y)  //如果next格子就是目标格子,那么退出
                {
                    break;
                }
                //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.代码写到现在,写的第一个结构体队列!作为一个当初自己瞎啃数据结构被难到哭泣的人,开森!

2.写完之后,虽然AC了,但还是发现不对,因为在while循环里套了一个for循环,所以判断到达目标状态后应该break两次,虽然有些繁琐,但还是暂且这样加在代码里。之前只有一个break的时候居然能通过,充分说明了noj的测例还是太宽松。

猜你喜欢

转载自blog.csdn.net/qq_41727666/article/details/82958029