POJ3083——Children of the Candy Corn

题目大意:

                  1. 迷宫,S是起点,E是终点,#是墙不可走,.可以走

                       2. 输出左转优先的步数

                       3.在输出右转优先的步数

                      4.在输出最短的步数

解题技巧:

                   ♢ 关键是方向转动的表示 可以用转向公式                  

                       左转,用数学式子表达就是  d=(d+1)%4;

                       右转,用数学式子表达就是  d=(d+3)%4;

                   ♢ 不论是左转优先还是右转优先,都用DFS

                         最短步数用BFS 求解  

注意要点:

                 需要注意一下“Exactly one 'S' and one 'E' will be present in the maze, and they will always be located along one        of    the maze edges and never in a corner.”即始点‘S’和终点‘E’一定都与迷宫的边界相邻,做题很关键。


//Time:0MS
//Memor:297K
#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#define  MAX 50

using namespace std;

struct point
{
    int  x , y;
    int step;
};

int visit[MAX][MAX];  //访问标志
char maze[MAX][MAX];  //存储迷宫
int  mov_left[4][2] = {{0,-1},{1,0},{0,1},{-1,0}} ; // 靠左走
int  mov_righ[4][2] = {{0,1},{1,0},{0,-1},{-1,0}} ; // 靠右走
int d1 , d2 ;
int start[2];    //起点
int finish[2];   //终点
int  w , h ;

int dfs(int x,int y,int d,int move[][2])
{
    int step ,temp , tx , ty ;
    if(x == finish[0] && y == finish[1])  // 剪枝
        return 1 ;
    for(int i = 0; i < 4 ; i++)
    {
        temp = (d + i) % 4 ;
        tx   =  x + move[temp][1] ;  //当前 x坐标
        ty   =  y + move[temp][0] ;  //当前 y坐标
        if(tx>=0 && tx<h && ty>=0 && ty<w && !visit[tx][ty])
            break ;
    }
    step = dfs(tx,ty,(temp + 3)%4,move) + 1;  //递归搜索 ,更新步数
    return step;
}

int bfs()                                //广搜求最短步数
{
    memset(visit,0,sizeof(visit));
    queue<point> Q;
    point p;
    p.x = start[0] ;
    p.y = start[1] ;
    p.step = 1;
    visit[p.x][p.y] = 1 ;
    Q.push(p);

    while(!Q.empty())
    {
        p = Q.front();
        Q.pop();
        if(p.x == finish[0] && p.y == finish[1])
            return p.step ;
        for(int i = 0 ; i < 4 ; i ++)
        {
            point temp ;
            temp.x = p.x + mov_left[i][1] ;
            temp.y = p.y + mov_left[i][0] ;
            if(temp.x>=0 && temp.x<h && temp.y>=0 && temp.y<w && maze[temp.x][temp.y]!='#' && !visit[temp.x][temp.y])
            {
                visit[temp.x][temp.y] = 1;
                temp.step = p.step + 1 ;
                Q.push(temp) ;
            }
        }
    }
    return 0;
}


int main()
{
    freopen("in.txt","r",stdin);
    int n;
    cin>>n;
    while(n--)
    {
        int i , j ;
        cin>>w>>h;
        memset(visit,0,sizeof(visit));

        for(i = 0; i < h; i++)
        {
            for(j = 0; j < w; j++)
            {
                cin>>maze[i][j];
                if(maze[i][j] == '#')   //障碍物不可走
                {
                    visit[i][j] = 1;
                }
                if(maze[i][j] == 'S') // 起点坐标
                {
                    start[0] = i ;
                    start[1] = j ;
                }
                if(maze[i][j] == 'E')  //终点坐标
                {
                    finish[0] = i ;
                    finish[1] = j ;
                }
            }
        }
        if(start[0] == 0)
        {
            d1 = 1 ;
            d2 = 1 ;
        }
        else if(start[0] == h-1)
        {
            d1 = 3 ;
            d2 = 3 ;
        }
        else if(start[0] == w-1)
        {
            d1 = 2 ;
            d2 = 0 ;
        }
        else
        {
            d1 = 0 ;
            d2 = 2 ;
        }
        cout<<dfs(start[0],start[1],d1,mov_left)<<" ";
        cout<<dfs(start[0],start[1],d2,mov_righ)<<" ";
        cout<<bfs()<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值